xref: /petsc/src/mat/interface/matrix.c (revision 31d4707089da71ebcff1fd00fbb3a11b50a9f3d1)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52    MatSetRandom - Sets all components of a matrix to random numbers.
53 
54    Logically Collective
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61    Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70    Notes:
71    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
72 
73    for sparse matrices that already have locations it fills the locations with random numbers.
74 
75    It generates an error if used on sparse matrices that have not been preallocated.
76 
77 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110    Logically Collective
111 
112    Input Parameter:
113 .  mat - the factored matrix
114 
115    Output Parameters:
116 +  pivot - the pivot value computed
117 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120    Level: advanced
121 
122    Notes:
123     This routine does not work for factorizations done with external packages.
124 
125     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
130           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscValidRealPointer(pivot, 2);
137   PetscValidIntPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144    MatFactorGetError - gets the error code from a factorization
145 
146    Logically Collective
147 
148    Input Parameter:
149 .  mat - the factored matrix
150 
151    Output Parameter:
152 .  err  - the error code
153 
154    Level: advanced
155 
156    Note:
157     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscValidPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172    MatFactorClearError - clears the error code in a factorization
173 
174    Logically Collective
175 
176    Input Parameter:
177 .  mat - the factored matrix
178 
179    Level: developer
180 
181    Note:
182     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 .    A  - the matrix
257 
258   Output Parameter:
259 .    keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264     `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscValidPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282       MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 .    A  - the matrix
286 
287   Output Parameter:
288 .    zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293     `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscValidPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323    Not Collective
324 
325    Input Parameter:
326 .   A - the matrix
327 
328    Output Parameter:
329 .   a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331    Level: advanced
332 
333    Notes:
334    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscValidPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361    Collective
362 
363    Input Parameter:
364 .  mat - the matrix
365 
366    Output Parameter:
367 .   trace - the sum of the diagonal entries
368 
369    Level: advanced
370 
371 .seealso: [](chapter_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscValidScalarPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388    MatRealPart - Zeros out the imaginary part of the matrix
389 
390    Logically Collective
391 
392    Input Parameter:
393 .  mat - the matrix
394 
395    Level: advanced
396 
397 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414    Collective
415 
416    Input Parameter:
417 .  mat - the matrix
418 
419    Output Parameters:
420 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 -   ghosts - the global indices of the ghost points
422 
423    Level: advanced
424 
425    Note:
426    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448    Logically Collective
449 
450    Input Parameter:
451 .  mat - the matrix
452 
453    Level: advanced
454 
455 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472    Not Collective
473 
474    Input Parameter:
475 .  mat - the matrix
476 
477    Output Parameters:
478 +  missing - is any diagonal missing
479 -  dd - first diagonal entry that is missing (optional) on this process
480 
481    Level: advanced
482 
483 .seealso: [](chapter_matrices), `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscValidBoolPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not `NULL`, the number of nonzeros in the row
510 .  cols - if not `NULL`, the column numbers
511 -  vals - if not `NULL`, the values
512 
513    Level: advanced
514 
515    Notes:
516    This routine is provided for people who need to have direct access
517    to the structure of a matrix.  We hope that we provide enough
518    high-level matrix routines that few users will need it.
519 
520    `MatGetRow()` always returns 0-based column indices, regardless of
521    whether the internal representation is 0-based (default) or 1-based.
522 
523    For better efficiency, set cols and/or vals to `NULL` if you do
524    not wish to extract these quantities.
525 
526    The user can only examine the values extracted with `MatGetRow()`;
527    the values cannot be altered.  To change the matrix entries, one
528    must use `MatSetValues()`.
529 
530    You can only have one call to `MatGetRow()` outstanding for a particular
531    matrix at a time, per processor. `MatGetRow()` can only obtain rows
532    associated with the given processor, it cannot get rows from the
533    other processors; for that we suggest using `MatCreateSubMatrices()`, then
534    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535    is in the global number of rows.
536 
537    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541    Fortran Note:
542    The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551    where maxcols >= maximum nonzeros in any row of the matrix.
552 
553    Caution:
554    Do not try to change the contents of the output arrays (`cols` and `vals`).
555    In some cases, this may corrupt the matrix.
556 
557 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective
581 
582    Input Parameter:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604    Not Collective
605 
606    Input Parameters:
607 +  mat - the matrix
608 .  row - the row to get
609 .  ncols - the number of nonzeros
610 .  cols - the columns of the nonzeros
611 -  vals - if nonzero the column values
612 
613    Level: advanced
614 
615    Notes:
616    This routine should be called after you have finished examining the entries.
617 
618    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619    us of the array after it has been restored. If you pass `NULL`, it will
620    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622    Fortran Notes:
623    The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632    Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635    before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscValidIntPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657    Not Collective
658 
659    Input Parameter:
660 .  mat - the matrix
661 
662    Level: advanced
663 
664    Note:
665    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.
666 
667 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685    Not Collective
686 
687    Input Parameter:
688 .  mat - the matrix
689 
690    Level: advanced
691 
692    Note:
693    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711    MatSetOptionsPrefix - Sets the prefix used for searching for all
712    `Mat` options in the database.
713 
714    Logically Collective
715 
716    Input Parameters:
717 +  A - the matrix
718 -  prefix - the prefix to prepend to all option names
719 
720    Level: advanced
721 
722    Notes:
723    A hyphen (-) must NOT be given at the beginning of the prefix name.
724    The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726    This is NOT used for options for the factorization of the matrix. Normally the
727    prefix is automatically passed in from the PC calling the factorization. To set
728    it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742    for matrices created with `MatGetFactor()`
743 
744    Logically Collective
745 
746    Input Parameters:
747 +  A - the matrix
748 -  prefix - the prefix to prepend to all option names for the factored matrix
749 
750    Level: developer
751 
752    Notes:
753    A hyphen (-) must NOT be given at the beginning of the prefix name.
754    The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscValidCharPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778    for matrices created with `MatGetFactor()`
779 
780    Logically Collective
781 
782    Input Parameters:
783 +  A - the matrix
784 -  prefix - the prefix to prepend to all option names for the factored matrix
785 
786    Level: developer
787 
788    Notes:
789    A hyphen (-) must NOT be given at the beginning of the prefix name.
790    The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822    matrix options in the database.
823 
824    Logically Collective
825 
826    Input Parameters:
827 +  A - the matrix
828 -  prefix - the prefix to prepend to all option names
829 
830    Level: advanced
831 
832    Note:
833    A hyphen (-) must NOT be given at the beginning of the prefix name.
834    The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847    MatGetOptionsPrefix - Gets the prefix used for searching for all
848    matrix options in the database.
849 
850    Not Collective
851 
852    Input Parameter:
853 .  A - the matrix
854 
855    Output Parameter:
856 .  prefix - pointer to the prefix string used
857 
858    Level: advanced
859 
860    Fortran Note:
861    The user should pass in a string `prefix` of
862    sufficient length to hold the prefix.
863 
864 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscValidPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
877 
878    Collective
879 
880    Input Parameter:
881 .  A - the matrix
882 
883    Level: beginner
884 
885    Notes:
886    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888    Users can reset the preallocation to access the original memory.
889 
890    Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
900   PetscFunctionReturn(PETSC_SUCCESS);
901 }
902 
903 /*@
904    MatSetUp - Sets up the internal matrix data structures for later use.
905 
906    Collective
907 
908    Input Parameter:
909 .  A - the matrix
910 
911    Level: intermediate
912 
913    Notes:
914    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
915    setting values in the matrix.
916 
917    If a suitable preallocation routine is used, this function does not need to be called.
918 
919    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*@C
945    MatViewFromOptions - View properties of the matrix based on options set in the options database
946 
947    Collective
948 
949    Input Parameters:
950 +  A - the matrix
951 .  obj - optional additional object that provides the options prefix to use
952 -  name - command line option
953 
954   Options Database Key:
955 .  -mat_view [viewertype]:... - the viewer and its options
956 
957    Level: intermediate
958 
959   Notes:
960 .vb
961     If no value is provided ascii:stdout is used
962        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
963                                                   for example ascii::ascii_info prints just the information about the object not all details
964                                                   unless :append is given filename opens in write mode, overwriting what was already there
965        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
966        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
967        socket[:port]                             defaults to the standard output port
968        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
969 .ve
970 
971 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
972 @*/
973 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
974 {
975   PetscFunctionBegin;
976   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
977   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
978   PetscFunctionReturn(PETSC_SUCCESS);
979 }
980 
981 /*@C
982    MatView - display information about a matrix in a variety ways
983 
984    Collective
985 
986    Input Parameters:
987 +  mat - the matrix
988 -  viewer - visualization context
989 
990    Options Database Keys:
991 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
992 .  -mat_view ::ascii_info_detail - Prints more detailed info
993 .  -mat_view - Prints matrix in ASCII format
994 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
995 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
996 .  -display <name> - Sets display name (default is host)
997 .  -draw_pause <sec> - Sets number of seconds to pause after display
998 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
999 .  -viewer_socket_machine <machine> -
1000 .  -viewer_socket_port <port> -
1001 .  -mat_view binary - save matrix to file in binary format
1002 -  -viewer_binary_filename <name> -
1003 
1004    Level: beginner
1005 
1006   Notes:
1007   The available visualization contexts include
1008 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1009 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1010 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1011 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1012 
1013    The user can open alternative visualization contexts with
1014 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1015 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1016          specified file; corresponding input uses MatLoad()
1017 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1018          an X window display
1019 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1020          Currently only the sequential dense and AIJ
1021          matrix types support the Socket viewer.
1022 
1023    The user can call `PetscViewerPushFormat()` to specify the output
1024    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1025    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1026 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1027 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1028 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1029 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1030          format common among all matrix types
1031 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1032          format (which is in many cases the same as the default)
1033 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1034          size and structure (not the matrix entries)
1035 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1036          the matrix structure
1037 
1038     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1039     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1040 
1041     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1042 
1043     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1044       viewer is used.
1045 
1046       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1047       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1048 
1049       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1050       and then use the following mouse functions.
1051 .vb
1052   left mouse: zoom in
1053   middle mouse: zoom out
1054   right mouse: continue with the simulation
1055 .ve
1056 
1057 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1058           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1059 @*/
1060 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1061 {
1062   PetscInt          rows, cols, rbs, cbs;
1063   PetscBool         isascii, isstring, issaws;
1064   PetscViewerFormat format;
1065   PetscMPIInt       size;
1066 
1067   PetscFunctionBegin;
1068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1069   PetscValidType(mat, 1);
1070   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1071   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1072   PetscCheckSameComm(mat, 1, viewer, 2);
1073 
1074   PetscCall(PetscViewerGetFormat(viewer, &format));
1075   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1076   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1077 
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1081   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");
1082 
1083   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1084   if (isascii) {
1085     if (!mat->preallocated) {
1086       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1087       PetscFunctionReturn(PETSC_SUCCESS);
1088     }
1089     if (!mat->assembled) {
1090       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1091       PetscFunctionReturn(PETSC_SUCCESS);
1092     }
1093     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1094     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1095       MatNullSpace nullsp, transnullsp;
1096 
1097       PetscCall(PetscViewerASCIIPushTab(viewer));
1098       PetscCall(MatGetSize(mat, &rows, &cols));
1099       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1100       if (rbs != 1 || cbs != 1) {
1101         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1102         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1103       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1104       if (mat->factortype) {
1105         MatSolverType solver;
1106         PetscCall(MatFactorGetSolverType(mat, &solver));
1107         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1108       }
1109       if (mat->ops->getinfo) {
1110         MatInfo info;
1111         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1112         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1113         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1114       }
1115       PetscCall(MatGetNullSpace(mat, &nullsp));
1116       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1117       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1118       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1119       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1120       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatProductView(mat, viewer));
1123       PetscCall(PetscViewerASCIIPopTab(viewer));
1124     }
1125   } else if (issaws) {
1126 #if defined(PETSC_HAVE_SAWS)
1127     PetscMPIInt rank;
1128 
1129     PetscCall(PetscObjectName((PetscObject)mat));
1130     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1131     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1132 #endif
1133   } else if (isstring) {
1134     const char *type;
1135     PetscCall(MatGetType(mat, &type));
1136     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1137     PetscTryTypeMethod(mat, view, viewer);
1138   }
1139   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1140     PetscCall(PetscViewerASCIIPushTab(viewer));
1141     PetscUseTypeMethod(mat, viewnative, viewer);
1142     PetscCall(PetscViewerASCIIPopTab(viewer));
1143   } else if (mat->ops->view) {
1144     PetscCall(PetscViewerASCIIPushTab(viewer));
1145     PetscUseTypeMethod(mat, view, viewer);
1146     PetscCall(PetscViewerASCIIPopTab(viewer));
1147   }
1148   if (isascii) {
1149     PetscCall(PetscViewerGetFormat(viewer, &format));
1150     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1151   }
1152   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1153   PetscFunctionReturn(PETSC_SUCCESS);
1154 }
1155 
1156 #if defined(PETSC_USE_DEBUG)
1157   #include <../src/sys/totalview/tv_data_display.h>
1158 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1159 {
1160   TV_add_row("Local rows", "int", &mat->rmap->n);
1161   TV_add_row("Local columns", "int", &mat->cmap->n);
1162   TV_add_row("Global rows", "int", &mat->rmap->N);
1163   TV_add_row("Global columns", "int", &mat->cmap->N);
1164   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1165   return TV_format_OK;
1166 }
1167 #endif
1168 
1169 /*@C
1170    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1171    with `MatView()`.  The matrix format is determined from the options database.
1172    Generates a parallel MPI matrix if the communicator has more than one
1173    processor.  The default matrix type is `MATAIJ`.
1174 
1175    Collective
1176 
1177    Input Parameters:
1178 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1179             or some related function before a call to `MatLoad()`
1180 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1181 
1182    Options Database Keys:
1183    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1184    block size
1185 .    -matload_block_size <bs> - set block size
1186 
1187    Level: beginner
1188 
1189    Notes:
1190    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1191    `Mat` before calling this routine if you wish to set it from the options database.
1192 
1193    `MatLoad()` automatically loads into the options database any options
1194    given in the file filename.info where filename is the name of the file
1195    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1196    file will be ignored if you use the -viewer_binary_skip_info option.
1197 
1198    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1199    sets the default matrix type AIJ and sets the local and global sizes.
1200    If type and/or size is already set, then the same are used.
1201 
1202    In parallel, each processor can load a subset of rows (or the
1203    entire matrix).  This routine is especially useful when a large
1204    matrix is stored on disk and only part of it is desired on each
1205    processor.  For example, a parallel solver may access only some of
1206    the rows from each processor.  The algorithm used here reads
1207    relatively small blocks of data rather than reading the entire
1208    matrix and then subsetting it.
1209 
1210    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1211    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1212    or the sequence like
1213 .vb
1214     `PetscViewer` v;
1215     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1216     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1217     `PetscViewerSetFromOptions`(v);
1218     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1219     `PetscViewerFileSetName`(v,"datafile");
1220 .ve
1221    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1222 $ -viewer_type {binary,hdf5}
1223 
1224    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1225    and src/mat/tutorials/ex10.c with the second approach.
1226 
1227    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1228    is read onto rank 0 and then shipped to its destination rank, one after another.
1229    Multiple objects, both matrices and vectors, can be stored within the same file.
1230    Their PetscObject name is ignored; they are loaded in the order of their storage.
1231 
1232    Most users should not need to know the details of the binary storage
1233    format, since `MatLoad()` and `MatView()` completely hide these details.
1234    But for anyone who's interested, the standard binary matrix storage
1235    format is
1236 
1237 .vb
1238     PetscInt    MAT_FILE_CLASSID
1239     PetscInt    number of rows
1240     PetscInt    number of columns
1241     PetscInt    total number of nonzeros
1242     PetscInt    *number nonzeros in each row
1243     PetscInt    *column indices of all nonzeros (starting index is zero)
1244     PetscScalar *values of all nonzeros
1245 .ve
1246 
1247    PETSc automatically does the byte swapping for
1248 machines that store the bytes reversed. Thus if you write your own binary
1249 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1250 and `PetscBinaryWrite()` to see how this may be done.
1251 
1252    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1253    Each processor's chunk is loaded independently by its owning rank.
1254    Multiple objects, both matrices and vectors, can be stored within the same file.
1255    They are looked up by their PetscObject name.
1256 
1257    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1258    by default the same structure and naming of the AIJ arrays and column count
1259    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1260 $    save example.mat A b -v7.3
1261    can be directly read by this routine (see Reference 1 for details).
1262 
1263    Depending on your MATLAB version, this format might be a default,
1264    otherwise you can set it as default in Preferences.
1265 
1266    Unless -nocompression flag is used to save the file in MATLAB,
1267    PETSc must be configured with ZLIB package.
1268 
1269    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1270 
1271    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1272 
1273    Corresponding `MatView()` is not yet implemented.
1274 
1275    The loaded matrix is actually a transpose of the original one in MATLAB,
1276    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1277    With this format, matrix is automatically transposed by PETSc,
1278    unless the matrix is marked as SPD or symmetric
1279    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1280 
1281    References:
1282 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1283 
1284 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1285  @*/
1286 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1287 {
1288   PetscBool flg;
1289 
1290   PetscFunctionBegin;
1291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1292   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1293 
1294   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1295 
1296   flg = PETSC_FALSE;
1297   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1298   if (flg) {
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1300     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1301   }
1302   flg = PETSC_FALSE;
1303   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1304   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1305 
1306   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1307   PetscUseTypeMethod(mat, load, viewer);
1308   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1309   PetscFunctionReturn(PETSC_SUCCESS);
1310 }
1311 
1312 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1313 {
1314   Mat_Redundant *redund = *redundant;
1315 
1316   PetscFunctionBegin;
1317   if (redund) {
1318     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1319       PetscCall(ISDestroy(&redund->isrow));
1320       PetscCall(ISDestroy(&redund->iscol));
1321       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1322     } else {
1323       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1324       PetscCall(PetscFree(redund->sbuf_j));
1325       PetscCall(PetscFree(redund->sbuf_a));
1326       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1327         PetscCall(PetscFree(redund->rbuf_j[i]));
1328         PetscCall(PetscFree(redund->rbuf_a[i]));
1329       }
1330       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1331     }
1332 
1333     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1334     PetscCall(PetscFree(redund));
1335   }
1336   PetscFunctionReturn(PETSC_SUCCESS);
1337 }
1338 
1339 /*@C
1340    MatDestroy - Frees space taken by a matrix.
1341 
1342    Collective
1343 
1344    Input Parameter:
1345 .  A - the matrix
1346 
1347    Level: beginner
1348 
1349    Developer Note:
1350    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1351    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1352    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1353    if changes are needed here.
1354 
1355 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1356 @*/
1357 PetscErrorCode MatDestroy(Mat *A)
1358 {
1359   PetscFunctionBegin;
1360   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1361   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1362   if (--((PetscObject)(*A))->refct > 0) {
1363     *A = NULL;
1364     PetscFunctionReturn(PETSC_SUCCESS);
1365   }
1366 
1367   /* if memory was published with SAWs then destroy it */
1368   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1369   PetscTryTypeMethod((*A), destroy);
1370 
1371   PetscCall(PetscFree((*A)->factorprefix));
1372   PetscCall(PetscFree((*A)->defaultvectype));
1373   PetscCall(PetscFree((*A)->defaultrandtype));
1374   PetscCall(PetscFree((*A)->bsizes));
1375   PetscCall(PetscFree((*A)->solvertype));
1376   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1377   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1378   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1379   PetscCall(MatProductClear(*A));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1382   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1383   PetscCall(MatDestroy(&(*A)->schur));
1384   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1385   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1386   PetscCall(PetscHeaderDestroy(A));
1387   PetscFunctionReturn(PETSC_SUCCESS);
1388 }
1389 
1390 /*@C
1391    MatSetValues - Inserts or adds a block of values into a matrix.
1392    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1393    MUST be called after all calls to `MatSetValues()` have been completed.
1394 
1395    Not Collective
1396 
1397    Input Parameters:
1398 +  mat - the matrix
1399 .  v - a logically two-dimensional array of values
1400 .  m - the number of rows
1401 .  idxm - the global indices of the rows
1402 .  n - the number of columns
1403 .  idxn - the global indices of the columns
1404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1405 
1406    Level: beginner
1407 
1408    Notes:
1409    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1410 
1411    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1412    options cannot be mixed without intervening calls to the assembly
1413    routines.
1414 
1415    `MatSetValues()` uses 0-based row and column numbers in Fortran
1416    as well as in C.
1417 
1418    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1419    simply ignored. This allows easily inserting element stiffness matrices
1420    with homogeneous Dirchlet boundary conditions that you don't want represented
1421    in the matrix.
1422 
1423    Efficiency Alert:
1424    The routine `MatSetValuesBlocked()` may offer much better efficiency
1425    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1426 
1427    Developer Note:
1428    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1429    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1430 
1431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1432           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1433 @*/
1434 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1435 {
1436   PetscFunctionBeginHot;
1437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1438   PetscValidType(mat, 1);
1439   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1440   PetscValidIntPointer(idxm, 3);
1441   PetscValidIntPointer(idxn, 5);
1442   MatCheckPreallocated(mat, 1);
1443 
1444   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1445   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1446 
1447   if (PetscDefined(USE_DEBUG)) {
1448     PetscInt i, j;
1449 
1450     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1451     for (i = 0; i < m; i++) {
1452       for (j = 0; j < n; j++) {
1453         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1454 #if defined(PETSC_USE_COMPLEX)
1455           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]);
1456 #else
1457           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]);
1458 #endif
1459       }
1460     }
1461     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);
1462     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);
1463   }
1464 
1465   if (mat->assembled) {
1466     mat->was_assembled = PETSC_TRUE;
1467     mat->assembled     = PETSC_FALSE;
1468   }
1469   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1470   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1471   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1472   PetscFunctionReturn(PETSC_SUCCESS);
1473 }
1474 
1475 /*@C
1476    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1477    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1478    MUST be called after all calls to `MatSetValues()` have been completed.
1479 
1480    Not Collective
1481 
1482    Input Parameters:
1483 +  mat - the matrix
1484 .  v - a logically two-dimensional array of values
1485 .  ism - the rows to provide
1486 .  isn - the columns to provide
1487 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1488 
1489    Level: beginner
1490 
1491    Notes:
1492    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1493 
1494    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1495    options cannot be mixed without intervening calls to the assembly
1496    routines.
1497 
1498    `MatSetValues()` uses 0-based row and column numbers in Fortran
1499    as well as in C.
1500 
1501    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1502    simply ignored. This allows easily inserting element stiffness matrices
1503    with homogeneous Dirchlet boundary conditions that you don't want represented
1504    in the matrix.
1505 
1506    Efficiency Alert:
1507    The routine `MatSetValuesBlocked()` may offer much better efficiency
1508    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1509 
1510     This is currently not optimized for any particular `ISType`
1511 
1512    Developer Notes:
1513     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1514                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1515 
1516 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1517           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1518 @*/
1519 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1520 {
1521   PetscInt        m, n;
1522   const PetscInt *rows, *cols;
1523 
1524   PetscFunctionBeginHot;
1525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1526   PetscCall(ISGetIndices(ism, &rows));
1527   PetscCall(ISGetIndices(isn, &cols));
1528   PetscCall(ISGetLocalSize(ism, &m));
1529   PetscCall(ISGetLocalSize(isn, &n));
1530   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1531   PetscCall(ISRestoreIndices(ism, &rows));
1532   PetscCall(ISRestoreIndices(isn, &cols));
1533   PetscFunctionReturn(PETSC_SUCCESS);
1534 }
1535 
1536 /*@
1537    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1538         values into a matrix
1539 
1540    Not Collective
1541 
1542    Input Parameters:
1543 +  mat - the matrix
1544 .  row - the (block) row to set
1545 -  v - a logically two-dimensional array of values
1546 
1547    Level: intermediate
1548 
1549    Notes:
1550    The values, `v`, are column-oriented (for the block version) and sorted
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    The matrix must have previously had its column indices set, likely by having been assembled.
1555 
1556    The row must belong to this process
1557 
1558 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1560 @*/
1561 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1562 {
1563   PetscInt globalrow;
1564 
1565   PetscFunctionBegin;
1566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1567   PetscValidType(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1570   PetscCall(MatSetValuesRow(mat, globalrow, v));
1571   PetscFunctionReturn(PETSC_SUCCESS);
1572 }
1573 
1574 /*@
1575    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1576         values into a matrix
1577 
1578    Not Collective
1579 
1580    Input Parameters:
1581 +  mat - the matrix
1582 .  row - the (block) row to set
1583 -  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
1584 
1585    Level: advanced
1586 
1587    Notes:
1588    The values, `v`, are column-oriented for the block version.
1589 
1590    All the nonzeros in the row must be provided
1591 
1592    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1593 
1594    The row must belong to this process
1595 
1596 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1597           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1598 @*/
1599 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1600 {
1601   PetscFunctionBeginHot;
1602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1603   PetscValidType(mat, 1);
1604   MatCheckPreallocated(mat, 1);
1605   PetscValidScalarPointer(v, 3);
1606   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1607   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1608   mat->insertmode = INSERT_VALUES;
1609 
1610   if (mat->assembled) {
1611     mat->was_assembled = PETSC_TRUE;
1612     mat->assembled     = PETSC_FALSE;
1613   }
1614   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1615   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1616   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1617   PetscFunctionReturn(PETSC_SUCCESS);
1618 }
1619 
1620 /*@
1621    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1622      Using structured grid indexing
1623 
1624    Not Collective
1625 
1626    Input Parameters:
1627 +  mat - the matrix
1628 .  m - number of rows being entered
1629 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1630 .  n - number of columns being entered
1631 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1632 .  v - a logically two-dimensional array of values
1633 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1634 
1635    Level: beginner
1636 
1637    Notes:
1638    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1639 
1640    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1641    options cannot be mixed without intervening calls to the assembly
1642    routines.
1643 
1644    The grid coordinates are across the entire grid, not just the local portion
1645 
1646    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1647    as well as in C.
1648 
1649    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1650 
1651    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1652    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1653 
1654    The columns and rows in the stencil passed in MUST be contained within the
1655    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1656    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1657    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1658    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1659 
1660    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1661    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1662    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1663    `DM_BOUNDARY_PERIODIC` boundary type.
1664 
1665    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
1666    a single value per point) you can skip filling those indices.
1667 
1668    Inspired by the structured grid interface to the HYPRE package
1669    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1670 
1671    Efficiency Alert:
1672    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1673    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1674 
1675    Fortran Note:
1676    `idxm` and `idxn` should be declared as
1677 $     MatStencil idxm(4,m),idxn(4,n)
1678    and the values inserted using
1679 .vb
1680     idxm(MatStencil_i,1) = i
1681     idxm(MatStencil_j,1) = j
1682     idxm(MatStencil_k,1) = k
1683     idxm(MatStencil_c,1) = c
1684     etc
1685 .ve
1686 
1687 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1688           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1689 @*/
1690 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1691 {
1692   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1693   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1694   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1695 
1696   PetscFunctionBegin;
1697   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1699   PetscValidType(mat, 1);
1700   PetscValidPointer(idxm, 3);
1701   PetscValidPointer(idxn, 5);
1702 
1703   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1704     jdxm = buf;
1705     jdxn = buf + m;
1706   } else {
1707     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1708     jdxm = bufm;
1709     jdxn = bufn;
1710   }
1711   for (i = 0; i < m; i++) {
1712     for (j = 0; j < 3 - sdim; j++) dxm++;
1713     tmp = *dxm++ - starts[0];
1714     for (j = 0; j < dim - 1; j++) {
1715       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1716       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1717     }
1718     if (mat->stencil.noc) dxm++;
1719     jdxm[i] = tmp;
1720   }
1721   for (i = 0; i < n; i++) {
1722     for (j = 0; j < 3 - sdim; j++) dxn++;
1723     tmp = *dxn++ - starts[0];
1724     for (j = 0; j < dim - 1; j++) {
1725       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1726       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1727     }
1728     if (mat->stencil.noc) dxn++;
1729     jdxn[i] = tmp;
1730   }
1731   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1732   PetscCall(PetscFree2(bufm, bufn));
1733   PetscFunctionReturn(PETSC_SUCCESS);
1734 }
1735 
1736 /*@
1737    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1738      Using structured grid indexing
1739 
1740    Not Collective
1741 
1742    Input Parameters:
1743 +  mat - the matrix
1744 .  m - number of rows being entered
1745 .  idxm - grid coordinates for matrix rows being entered
1746 .  n - number of columns being entered
1747 .  idxn - grid coordinates for matrix columns being entered
1748 .  v - a logically two-dimensional array of values
1749 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1750 
1751    Level: beginner
1752 
1753    Notes:
1754    By default the values, `v`, are row-oriented and unsorted.
1755    See `MatSetOption()` for other options.
1756 
1757    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1758    options cannot be mixed without intervening calls to the assembly
1759    routines.
1760 
1761    The grid coordinates are across the entire grid, not just the local portion
1762 
1763    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1764    as well as in C.
1765 
1766    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1767 
1768    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1769    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1770 
1771    The columns and rows in the stencil passed in MUST be contained within the
1772    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1773    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1774    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1775    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1776 
1777    Negative indices may be passed in idxm and idxn, these rows and columns are
1778    simply ignored. This allows easily inserting element stiffness matrices
1779    with homogeneous Dirchlet boundary conditions that you don't want represented
1780    in the matrix.
1781 
1782    Inspired by the structured grid interface to the HYPRE package
1783    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1784 
1785    Fortran Note:
1786    `idxm` and `idxn` should be declared as
1787 $     MatStencil idxm(4,m),idxn(4,n)
1788    and the values inserted using
1789 .vb
1790     idxm(MatStencil_i,1) = i
1791     idxm(MatStencil_j,1) = j
1792     idxm(MatStencil_k,1) = k
1793    etc
1794 .ve
1795 
1796 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1798           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1799 @*/
1800 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1801 {
1802   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1803   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1804   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1805 
1806   PetscFunctionBegin;
1807   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1809   PetscValidType(mat, 1);
1810   PetscValidPointer(idxm, 3);
1811   PetscValidPointer(idxn, 5);
1812   PetscValidScalarPointer(v, 6);
1813 
1814   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1815     jdxm = buf;
1816     jdxn = buf + m;
1817   } else {
1818     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1819     jdxm = bufm;
1820     jdxn = bufn;
1821   }
1822   for (i = 0; i < m; i++) {
1823     for (j = 0; j < 3 - sdim; j++) dxm++;
1824     tmp = *dxm++ - starts[0];
1825     for (j = 0; j < sdim - 1; j++) {
1826       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1827       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1828     }
1829     dxm++;
1830     jdxm[i] = tmp;
1831   }
1832   for (i = 0; i < n; i++) {
1833     for (j = 0; j < 3 - sdim; j++) dxn++;
1834     tmp = *dxn++ - starts[0];
1835     for (j = 0; j < sdim - 1; j++) {
1836       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1837       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1838     }
1839     dxn++;
1840     jdxn[i] = tmp;
1841   }
1842   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1843   PetscCall(PetscFree2(bufm, bufn));
1844   PetscFunctionReturn(PETSC_SUCCESS);
1845 }
1846 
1847 /*@
1848    MatSetStencil - Sets the grid information for setting values into a matrix via
1849         `MatSetValuesStencil()`
1850 
1851    Not Collective
1852 
1853    Input Parameters:
1854 +  mat - the matrix
1855 .  dim - dimension of the grid 1, 2, or 3
1856 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1857 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1858 -  dof - number of degrees of freedom per node
1859 
1860    Level: beginner
1861 
1862    Notes:
1863    Inspired by the structured grid interface to the HYPRE package
1864    (www.llnl.gov/CASC/hyper)
1865 
1866    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1867    user.
1868 
1869 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1870           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1871 @*/
1872 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1873 {
1874   PetscFunctionBegin;
1875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1876   PetscValidIntPointer(dims, 3);
1877   PetscValidIntPointer(starts, 4);
1878 
1879   mat->stencil.dim = dim + (dof > 1);
1880   for (PetscInt i = 0; i < dim; i++) {
1881     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1882     mat->stencil.starts[i] = starts[dim - i - 1];
1883   }
1884   mat->stencil.dims[dim]   = dof;
1885   mat->stencil.starts[dim] = 0;
1886   mat->stencil.noc         = (PetscBool)(dof == 1);
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@C
1891    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1892 
1893    Not Collective
1894 
1895    Input Parameters:
1896 +  mat - the matrix
1897 .  v - a logically two-dimensional array of values
1898 .  m  - the number of block rows
1899 .  idxm - the global block indices
1900 .  n - the number of block columns
1901 .  idxn - the global block indices
1902 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1903 
1904    Level: intermediate
1905 
1906    Notes:
1907    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1908    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1909 
1910    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1911    NOT the total number of rows/columns; for example, if the block size is 2 and
1912    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1913    The values in idxm would be 1 2; that is the first index for each block divided by
1914    the block size.
1915 
1916    You must call `MatSetBlockSize()` when constructing this matrix (before
1917    preallocating it).
1918 
1919    By default the values, `v`, are row-oriented, so the layout of
1920    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1921 
1922    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1923    options cannot be mixed without intervening calls to the assembly
1924    routines.
1925 
1926    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1927    as well as in C.
1928 
1929    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1930    simply ignored. This allows easily inserting element stiffness matrices
1931    with homogeneous Dirchlet boundary conditions that you don't want represented
1932    in the matrix.
1933 
1934    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1935    internal searching must be done to determine where to place the
1936    data in the matrix storage space.  By instead inserting blocks of
1937    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1938    reduced.
1939 
1940    Example:
1941 .vb
1942    Suppose m=n=2 and block size(bs) = 2 The array is
1943 
1944    1  2  | 3  4
1945    5  6  | 7  8
1946    - - - | - - -
1947    9  10 | 11 12
1948    13 14 | 15 16
1949 
1950    v[] should be passed in like
1951    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1952 
1953   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1954    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1955 .ve
1956 
1957 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1958 @*/
1959 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1960 {
1961   PetscFunctionBeginHot;
1962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1963   PetscValidType(mat, 1);
1964   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1965   PetscValidIntPointer(idxm, 3);
1966   PetscValidIntPointer(idxn, 5);
1967   MatCheckPreallocated(mat, 1);
1968   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1969   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1970   if (PetscDefined(USE_DEBUG)) {
1971     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1972     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1973   }
1974   if (PetscDefined(USE_DEBUG)) {
1975     PetscInt rbs, cbs, M, N, i;
1976     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1977     PetscCall(MatGetSize(mat, &M, &N));
1978     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);
1979     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);
1980   }
1981   if (mat->assembled) {
1982     mat->was_assembled = PETSC_TRUE;
1983     mat->assembled     = PETSC_FALSE;
1984   }
1985   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1986   if (mat->ops->setvaluesblocked) {
1987     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1988   } else {
1989     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1990     PetscInt i, j, bs, cbs;
1991 
1992     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1993     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1994       iidxm = buf;
1995       iidxn = buf + m * bs;
1996     } else {
1997       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1998       iidxm = bufr;
1999       iidxn = bufc;
2000     }
2001     for (i = 0; i < m; i++) {
2002       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2003     }
2004     if (m != n || bs != cbs || idxm != idxn) {
2005       for (i = 0; i < n; i++) {
2006         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2007       }
2008     } else iidxn = iidxm;
2009     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2010     PetscCall(PetscFree2(bufr, bufc));
2011   }
2012   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2013   PetscFunctionReturn(PETSC_SUCCESS);
2014 }
2015 
2016 /*@C
2017    MatGetValues - Gets a block of local values from a matrix.
2018 
2019    Not Collective; can only return values that are owned by the give process
2020 
2021    Input Parameters:
2022 +  mat - the matrix
2023 .  v - a logically two-dimensional array for storing the values
2024 .  m  - the number of rows
2025 .  idxm - the  global indices of the rows
2026 .  n - the number of columns
2027 -  idxn - the global indices of the columns
2028 
2029    Level: advanced
2030 
2031    Notes:
2032      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2033      The values, `v`, are then returned in a row-oriented format,
2034      analogous to that used by default in `MatSetValues()`.
2035 
2036      `MatGetValues()` uses 0-based row and column numbers in
2037      Fortran as well as in C.
2038 
2039      `MatGetValues()` requires that the matrix has been assembled
2040      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2041      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2042      without intermediate matrix assembly.
2043 
2044      Negative row or column indices will be ignored and those locations in `v` will be
2045      left unchanged.
2046 
2047      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2048      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2049      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2050 
2051 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2052 @*/
2053 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2054 {
2055   PetscFunctionBegin;
2056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2057   PetscValidType(mat, 1);
2058   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2059   PetscValidIntPointer(idxm, 3);
2060   PetscValidIntPointer(idxn, 5);
2061   PetscValidScalarPointer(v, 6);
2062   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2063   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2064   MatCheckPreallocated(mat, 1);
2065 
2066   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2067   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2068   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2069   PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 
2072 /*@C
2073    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2074      defined previously by `MatSetLocalToGlobalMapping()`
2075 
2076    Not Collective
2077 
2078    Input Parameters:
2079 +  mat - the matrix
2080 .  nrow - number of rows
2081 .  irow - the row local indices
2082 .  ncol - number of columns
2083 -  icol - the column local indices
2084 
2085    Output Parameter:
2086 .  y -  a logically two-dimensional array of values
2087 
2088    Level: advanced
2089 
2090    Notes:
2091      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2092 
2093      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,
2094      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2095      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2096      with `MatSetLocalToGlobalMapping()`.
2097 
2098    Developer Note:
2099       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2100       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2101 
2102 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2103           `MatSetValuesLocal()`, `MatGetValues()`
2104 @*/
2105 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2106 {
2107   PetscFunctionBeginHot;
2108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2109   PetscValidType(mat, 1);
2110   MatCheckPreallocated(mat, 1);
2111   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2112   PetscValidIntPointer(irow, 3);
2113   PetscValidIntPointer(icol, 5);
2114   if (PetscDefined(USE_DEBUG)) {
2115     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2116     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2117   }
2118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2119   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2120   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2121   else {
2122     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2123     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2124       irowm = buf;
2125       icolm = buf + nrow;
2126     } else {
2127       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2128       irowm = bufr;
2129       icolm = bufc;
2130     }
2131     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2134     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2135     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2136     PetscCall(PetscFree2(bufr, bufc));
2137   }
2138   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2139   PetscFunctionReturn(PETSC_SUCCESS);
2140 }
2141 
2142 /*@
2143   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2144   the same size. Currently, this can only be called once and creates the given matrix.
2145 
2146   Not Collective
2147 
2148   Input Parameters:
2149 + mat - the matrix
2150 . nb - the number of blocks
2151 . bs - the number of rows (and columns) in each block
2152 . rows - a concatenation of the rows for each block
2153 - v - a concatenation of logically two-dimensional arrays of values
2154 
2155   Level: advanced
2156 
2157   Note:
2158   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2159 
2160   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2161 
2162 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2163           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2164 @*/
2165 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2166 {
2167   PetscFunctionBegin;
2168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2169   PetscValidType(mat, 1);
2170   PetscValidIntPointer(rows, 4);
2171   PetscValidScalarPointer(v, 5);
2172   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2173 
2174   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2175   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2176   else {
2177     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2178   }
2179   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@
2184    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2185    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2186    using a local (per-processor) numbering.
2187 
2188    Not Collective
2189 
2190    Input Parameters:
2191 +  x - the matrix
2192 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2193 -  cmapping - column mapping
2194 
2195    Level: intermediate
2196 
2197    Note:
2198    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2199 
2200 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2201 @*/
2202 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2203 {
2204   PetscFunctionBegin;
2205   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2206   PetscValidType(x, 1);
2207   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2208   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2209   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2210   else {
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2213   }
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@
2218    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2219 
2220    Not Collective
2221 
2222    Input Parameter:
2223 .  A - the matrix
2224 
2225    Output Parameters:
2226 + rmapping - row mapping
2227 - cmapping - column mapping
2228 
2229    Level: advanced
2230 
2231 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2237   PetscValidType(A, 1);
2238   if (rmapping) {
2239     PetscValidPointer(rmapping, 2);
2240     *rmapping = A->rmap->mapping;
2241   }
2242   if (cmapping) {
2243     PetscValidPointer(cmapping, 3);
2244     *cmapping = A->cmap->mapping;
2245   }
2246   PetscFunctionReturn(PETSC_SUCCESS);
2247 }
2248 
2249 /*@
2250    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2251 
2252    Logically Collective
2253 
2254    Input Parameters:
2255 +  A - the matrix
2256 . rmap - row layout
2257 - cmap - column layout
2258 
2259    Level: advanced
2260 
2261    Note:
2262    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2263 
2264 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2265 @*/
2266 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2267 {
2268   PetscFunctionBegin;
2269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2270   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2271   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2272   PetscFunctionReturn(PETSC_SUCCESS);
2273 }
2274 
2275 /*@
2276    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2277 
2278    Not Collective
2279 
2280    Input Parameter:
2281 .  A - the matrix
2282 
2283    Output Parameters:
2284 + rmap - row layout
2285 - cmap - column layout
2286 
2287    Level: advanced
2288 
2289 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2290 @*/
2291 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2292 {
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2295   PetscValidType(A, 1);
2296   if (rmap) {
2297     PetscValidPointer(rmap, 2);
2298     *rmap = A->rmap;
2299   }
2300   if (cmap) {
2301     PetscValidPointer(cmap, 3);
2302     *cmap = A->cmap;
2303   }
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@C
2308    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2309    using a local numbering of the nodes.
2310 
2311    Not Collective
2312 
2313    Input Parameters:
2314 +  mat - the matrix
2315 .  nrow - number of rows
2316 .  irow - the row local indices
2317 .  ncol - number of columns
2318 .  icol - the column local indices
2319 .  y -  a logically two-dimensional array of values
2320 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2321 
2322    Level: intermediate
2323 
2324    Notes:
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2326       `MatSetUp()` before using this routine
2327 
2328    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2329 
2330    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2331    options cannot be mixed without intervening calls to the assembly
2332    routines.
2333 
2334    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2335    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2336 
2337    Developer Note:
2338     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2339                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2340 
2341 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2342           `MatGetValuesLocal()`
2343 @*/
2344 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2345 {
2346   PetscFunctionBeginHot;
2347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2348   PetscValidType(mat, 1);
2349   MatCheckPreallocated(mat, 1);
2350   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2351   PetscValidIntPointer(irow, 3);
2352   PetscValidIntPointer(icol, 5);
2353   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2354   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2355   if (PetscDefined(USE_DEBUG)) {
2356     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2357     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2358   }
2359 
2360   if (mat->assembled) {
2361     mat->was_assembled = PETSC_TRUE;
2362     mat->assembled     = PETSC_FALSE;
2363   }
2364   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2365   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2366   else {
2367     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2368     const PetscInt *irowm, *icolm;
2369 
2370     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2371       bufr  = buf;
2372       bufc  = buf + nrow;
2373       irowm = bufr;
2374       icolm = bufc;
2375     } else {
2376       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2377       irowm = bufr;
2378       icolm = bufc;
2379     }
2380     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2381     else irowm = irow;
2382     if (mat->cmap->mapping) {
2383       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2384         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2385       } else icolm = irowm;
2386     } else icolm = icol;
2387     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2388     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2389   }
2390   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2391   PetscFunctionReturn(PETSC_SUCCESS);
2392 }
2393 
2394 /*@C
2395    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2396    using a local ordering of the nodes a block at a time.
2397 
2398    Not Collective
2399 
2400    Input Parameters:
2401 +  x - the matrix
2402 .  nrow - number of rows
2403 .  irow - the row local indices
2404 .  ncol - number of columns
2405 .  icol - the column local indices
2406 .  y -  a logically two-dimensional array of values
2407 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2408 
2409    Level: intermediate
2410 
2411    Notes:
2412    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2413       `MatSetUp()` before using this routine
2414 
2415    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2416       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2417 
2418    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2419    options cannot be mixed without intervening calls to the assembly
2420    routines.
2421 
2422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2423    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2424 
2425    Developer Note:
2426     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2427                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2428 
2429 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2430           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2431 @*/
2432 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2433 {
2434   PetscFunctionBeginHot;
2435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2436   PetscValidType(mat, 1);
2437   MatCheckPreallocated(mat, 1);
2438   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2439   PetscValidIntPointer(irow, 3);
2440   PetscValidIntPointer(icol, 5);
2441   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2442   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2443   if (PetscDefined(USE_DEBUG)) {
2444     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2445     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);
2446   }
2447 
2448   if (mat->assembled) {
2449     mat->was_assembled = PETSC_TRUE;
2450     mat->assembled     = PETSC_FALSE;
2451   }
2452   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2453     PetscInt irbs, rbs;
2454     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2455     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2456     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2457   }
2458   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2459     PetscInt icbs, cbs;
2460     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2461     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2462     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2463   }
2464   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2465   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2466   else {
2467     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2468     const PetscInt *irowm, *icolm;
2469 
2470     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2471       bufr  = buf;
2472       bufc  = buf + nrow;
2473       irowm = bufr;
2474       icolm = bufc;
2475     } else {
2476       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2477       irowm = bufr;
2478       icolm = bufc;
2479     }
2480     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2481     else irowm = irow;
2482     if (mat->cmap->mapping) {
2483       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2484         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2485       } else icolm = irowm;
2486     } else icolm = icol;
2487     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2488     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2489   }
2490   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2491   PetscFunctionReturn(PETSC_SUCCESS);
2492 }
2493 
2494 /*@
2495    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2496 
2497    Collective
2498 
2499    Input Parameters:
2500 +  mat - the matrix
2501 -  x   - the vector to be multiplied
2502 
2503    Output Parameter:
2504 .  y - the result
2505 
2506    Level: developer
2507 
2508    Note:
2509    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2510    call `MatMultDiagonalBlock`(A,y,y).
2511 
2512 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2513 @*/
2514 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2515 {
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2518   PetscValidType(mat, 1);
2519   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2520   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2521 
2522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2524   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2525   MatCheckPreallocated(mat, 1);
2526 
2527   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2528   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2529   PetscFunctionReturn(PETSC_SUCCESS);
2530 }
2531 
2532 /*@
2533    MatMult - Computes the matrix-vector product, y = Ax.
2534 
2535    Neighbor-wise Collective
2536 
2537    Input Parameters:
2538 +  mat - the matrix
2539 -  x   - the vector to be multiplied
2540 
2541    Output Parameter:
2542 .  y - the result
2543 
2544    Level: beginner
2545 
2546    Note:
2547    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2548    call `MatMult`(A,y,y).
2549 
2550 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2551 @*/
2552 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2553 {
2554   PetscFunctionBegin;
2555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2556   PetscValidType(mat, 1);
2557   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2558   VecCheckAssembled(x);
2559   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2562   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2563   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);
2564   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);
2565   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);
2566   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);
2567   PetscCall(VecSetErrorIfLocked(y, 3));
2568   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2569   MatCheckPreallocated(mat, 1);
2570 
2571   PetscCall(VecLockReadPush(x));
2572   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2573   PetscUseTypeMethod(mat, mult, x, y);
2574   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2575   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2576   PetscCall(VecLockReadPop(x));
2577   PetscFunctionReturn(PETSC_SUCCESS);
2578 }
2579 
2580 /*@
2581    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2582 
2583    Neighbor-wise Collective
2584 
2585    Input Parameters:
2586 +  mat - the matrix
2587 -  x   - the vector to be multiplied
2588 
2589    Output Parameter:
2590 .  y - the result
2591 
2592    Level: beginner
2593 
2594    Notes:
2595    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2596    call `MatMultTranspose`(A,y,y).
2597 
2598    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2599    use `MatMultHermitianTranspose()`
2600 
2601 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2602 @*/
2603 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2604 {
2605   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2606 
2607   PetscFunctionBegin;
2608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2609   PetscValidType(mat, 1);
2610   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2611   VecCheckAssembled(x);
2612   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2613 
2614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2616   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2617   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);
2618   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);
2619   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);
2620   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);
2621   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2622   MatCheckPreallocated(mat, 1);
2623 
2624   if (!mat->ops->multtranspose) {
2625     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2626     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);
2627   } else op = mat->ops->multtranspose;
2628   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2629   PetscCall(VecLockReadPush(x));
2630   PetscCall((*op)(mat, x, y));
2631   PetscCall(VecLockReadPop(x));
2632   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2633   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2634   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2635   PetscFunctionReturn(PETSC_SUCCESS);
2636 }
2637 
2638 /*@
2639    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2640 
2641    Neighbor-wise Collective
2642 
2643    Input Parameters:
2644 +  mat - the matrix
2645 -  x   - the vector to be multilplied
2646 
2647    Output Parameter:
2648 .  y - the result
2649 
2650    Level: beginner
2651 
2652    Notes:
2653    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2654    call `MatMultHermitianTranspose`(A,y,y).
2655 
2656    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2657 
2658    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2659 
2660 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2661 @*/
2662 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2663 {
2664   PetscFunctionBegin;
2665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2666   PetscValidType(mat, 1);
2667   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2668   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2669 
2670   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2671   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2672   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2673   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);
2674   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);
2675   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);
2676   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);
2677   MatCheckPreallocated(mat, 1);
2678 
2679   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2680 #if defined(PETSC_USE_COMPLEX)
2681   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2682     PetscCall(VecLockReadPush(x));
2683     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2684     else PetscUseTypeMethod(mat, mult, x, y);
2685     PetscCall(VecLockReadPop(x));
2686   } else {
2687     Vec w;
2688     PetscCall(VecDuplicate(x, &w));
2689     PetscCall(VecCopy(x, w));
2690     PetscCall(VecConjugate(w));
2691     PetscCall(MatMultTranspose(mat, w, y));
2692     PetscCall(VecDestroy(&w));
2693     PetscCall(VecConjugate(y));
2694   }
2695   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2696 #else
2697   PetscCall(MatMultTranspose(mat, x, y));
2698 #endif
2699   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2700   PetscFunctionReturn(PETSC_SUCCESS);
2701 }
2702 
2703 /*@
2704     MatMultAdd -  Computes v3 = v2 + A * v1.
2705 
2706     Neighbor-wise Collective
2707 
2708     Input Parameters:
2709 +   mat - the matrix
2710 .   v1 - the vector to be multiplied by `mat`
2711 -   v2 - the vector to be added to the result
2712 
2713     Output Parameter:
2714 .   v3 - the result
2715 
2716     Level: beginner
2717 
2718     Note:
2719     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2720     call `MatMultAdd`(A,v1,v2,v1).
2721 
2722 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2723 @*/
2724 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2725 {
2726   PetscFunctionBegin;
2727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2728   PetscValidType(mat, 1);
2729   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2730   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2731   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2732 
2733   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2735   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);
2736   /* 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);
2737      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); */
2738   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);
2739   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);
2740   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2741   MatCheckPreallocated(mat, 1);
2742 
2743   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2744   PetscCall(VecLockReadPush(v1));
2745   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2746   PetscCall(VecLockReadPop(v1));
2747   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2748   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 /*@
2753    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2754 
2755    Neighbor-wise Collective
2756 
2757    Input Parameters:
2758 +  mat - the matrix
2759 .  v1 - the vector to be multiplied by the transpose of the matrix
2760 -  v2 - the vector to be added to the result
2761 
2762    Output Parameter:
2763 .  v3 - the result
2764 
2765    Level: beginner
2766 
2767    Note:
2768    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2769    call `MatMultTransposeAdd`(A,v1,v2,v1).
2770 
2771 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2772 @*/
2773 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2774 {
2775   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2776 
2777   PetscFunctionBegin;
2778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2779   PetscValidType(mat, 1);
2780   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2781   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2782   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2783 
2784   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2785   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2786   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);
2787   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);
2788   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);
2789   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2790   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2791   MatCheckPreallocated(mat, 1);
2792 
2793   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2794   PetscCall(VecLockReadPush(v1));
2795   PetscCall((*op)(mat, v1, v2, v3));
2796   PetscCall(VecLockReadPop(v1));
2797   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2798   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2799   PetscFunctionReturn(PETSC_SUCCESS);
2800 }
2801 
2802 /*@
2803    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2804 
2805    Neighbor-wise Collective
2806 
2807    Input Parameters:
2808 +  mat - the matrix
2809 .  v1 - the vector to be multiplied by the Hermitian transpose
2810 -  v2 - the vector to be added to the result
2811 
2812    Output Parameter:
2813 .  v3 - the result
2814 
2815    Level: beginner
2816 
2817    Note:
2818    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2819    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2820 
2821 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2822 @*/
2823 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2824 {
2825   PetscFunctionBegin;
2826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2827   PetscValidType(mat, 1);
2828   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2829   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2830   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2831 
2832   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2833   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2834   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2835   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);
2836   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);
2837   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);
2838   MatCheckPreallocated(mat, 1);
2839 
2840   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2841   PetscCall(VecLockReadPush(v1));
2842   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2843   else {
2844     Vec w, z;
2845     PetscCall(VecDuplicate(v1, &w));
2846     PetscCall(VecCopy(v1, w));
2847     PetscCall(VecConjugate(w));
2848     PetscCall(VecDuplicate(v3, &z));
2849     PetscCall(MatMultTranspose(mat, w, z));
2850     PetscCall(VecDestroy(&w));
2851     PetscCall(VecConjugate(z));
2852     if (v2 != v3) {
2853       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2854     } else {
2855       PetscCall(VecAXPY(v3, 1.0, z));
2856     }
2857     PetscCall(VecDestroy(&z));
2858   }
2859   PetscCall(VecLockReadPop(v1));
2860   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2861   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2862   PetscFunctionReturn(PETSC_SUCCESS);
2863 }
2864 
2865 /*@C
2866    MatGetFactorType - gets the type of factorization it is
2867 
2868    Not Collective
2869 
2870    Input Parameter:
2871 .  mat - the matrix
2872 
2873    Output Parameter:
2874 .  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`
2875 
2876    Level: intermediate
2877 
2878 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2879           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2880 @*/
2881 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2882 {
2883   PetscFunctionBegin;
2884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2885   PetscValidType(mat, 1);
2886   PetscValidPointer(t, 2);
2887   *t = mat->factortype;
2888   PetscFunctionReturn(PETSC_SUCCESS);
2889 }
2890 
2891 /*@C
2892    MatSetFactorType - sets the type of factorization it is
2893 
2894    Logically Collective
2895 
2896    Input Parameters:
2897 +  mat - the matrix
2898 -  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`
2899 
2900    Level: intermediate
2901 
2902 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2903           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2904 @*/
2905 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2906 {
2907   PetscFunctionBegin;
2908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2909   PetscValidType(mat, 1);
2910   mat->factortype = t;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915    MatGetInfo - Returns information about matrix storage (number of
2916    nonzeros, memory, etc.).
2917 
2918    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2919 
2920    Input Parameters:
2921 +  mat - the matrix
2922 -  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)
2923 
2924    Output Parameter:
2925 .  info - matrix information context
2926 
2927    Notes:
2928    The `MatInfo` context contains a variety of matrix data, including
2929    number of nonzeros allocated and used, number of mallocs during
2930    matrix assembly, etc.  Additional information for factored matrices
2931    is provided (such as the fill ratio, number of mallocs during
2932    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2933    when using the runtime options
2934 $       -info -mat_view ::ascii_info
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(mat, MAT_CLASSID, 2);
3146   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3147   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3148   if (info) PetscValidPointer(info, 5);
3149   PetscValidType(mat, 2);
3150   PetscValidPointer(fact, 1);
3151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3153   if (!(fact)->ops->lufactorsymbolic) {
3154     MatSolverType stype;
3155     PetscCall(MatFactorGetSolverType(fact, &stype));
3156     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3157   }
3158   MatCheckPreallocated(mat, 2);
3159   if (!info) {
3160     PetscCall(MatFactorInfoInitialize(&tinfo));
3161     info = &tinfo;
3162   }
3163 
3164   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3165   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3166   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3167   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3168   PetscFunctionReturn(PETSC_SUCCESS);
3169 }
3170 
3171 /*@C
3172    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3173    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3174 
3175    Collective
3176 
3177    Input Parameters:
3178 +  fact - the factor matrix obtained with `MatGetFactor()`
3179 .  mat - the matrix
3180 -  info - options for factorization
3181 
3182    Level: developer
3183 
3184    Notes:
3185    See `MatLUFactor()` for in-place factorization.  See
3186    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3187 
3188    Most users should employ the `KSP` interface for linear solvers
3189    instead of working directly with matrix algebra routines such as this.
3190    See, e.g., `KSPCreate()`.
3191 
3192     Developer Note:
3193     The Fortran interface is not autogenerated as the
3194     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3195 
3196 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3197 @*/
3198 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3199 {
3200   MatFactorInfo tinfo;
3201 
3202   PetscFunctionBegin;
3203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3204   PetscValidType(mat, 2);
3205   PetscValidPointer(fact, 1);
3206   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3208   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,
3209              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3210 
3211   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3212   MatCheckPreallocated(mat, 2);
3213   if (!info) {
3214     PetscCall(MatFactorInfoInitialize(&tinfo));
3215     info = &tinfo;
3216   }
3217 
3218   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3219   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3220   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3221   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3222   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3223   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3224   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3225   PetscFunctionReturn(PETSC_SUCCESS);
3226 }
3227 
3228 /*@C
3229    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3230    symmetric matrix.
3231 
3232    Collective
3233 
3234    Input Parameters:
3235 +  mat - the matrix
3236 .  perm - row and column permutations
3237 -  f - expected fill as ratio of original fill
3238 
3239    Level: developer
3240 
3241    Notes:
3242    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3243    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3244 
3245    Most users should employ the `KSP` interface for linear solvers
3246    instead of working directly with matrix algebra routines such as this.
3247    See, e.g., `KSPCreate()`.
3248 
3249    Developer Note:
3250    The Fortran interface is not autogenerated as the
3251    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3252 
3253 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3254           `MatGetOrdering()`
3255 @*/
3256 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3257 {
3258   MatFactorInfo tinfo;
3259 
3260   PetscFunctionBegin;
3261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3262   PetscValidType(mat, 1);
3263   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3264   if (info) PetscValidPointer(info, 3);
3265   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3268   MatCheckPreallocated(mat, 1);
3269   if (!info) {
3270     PetscCall(MatFactorInfoInitialize(&tinfo));
3271     info = &tinfo;
3272   }
3273 
3274   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3275   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3276   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3277   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3278   PetscFunctionReturn(PETSC_SUCCESS);
3279 }
3280 
3281 /*@C
3282    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3283    of a symmetric matrix.
3284 
3285    Collective
3286 
3287    Input Parameters:
3288 +  fact - the factor matrix obtained with `MatGetFactor()`
3289 .  mat - the matrix
3290 .  perm - row and column permutations
3291 -  info - options for factorization, includes
3292 .vb
3293           fill - expected fill as ratio of original fill.
3294           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3295                    Run with the option -info to determine an optimal value to use
3296 .ve
3297 
3298    Level: developer
3299 
3300    Notes:
3301    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3302    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3303 
3304    Most users should employ the `KSP` interface for linear solvers
3305    instead of working directly with matrix algebra routines such as this.
3306    See, e.g., `KSPCreate()`.
3307 
3308    Developer Note:
3309    The Fortran interface is not autogenerated as the
3310    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3311 
3312 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3313           `MatGetOrdering()`
3314 @*/
3315 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3316 {
3317   MatFactorInfo tinfo;
3318 
3319   PetscFunctionBegin;
3320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3321   PetscValidType(mat, 2);
3322   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3323   if (info) PetscValidPointer(info, 4);
3324   PetscValidPointer(fact, 1);
3325   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3328   if (!(fact)->ops->choleskyfactorsymbolic) {
3329     MatSolverType stype;
3330     PetscCall(MatFactorGetSolverType(fact, &stype));
3331     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3332   }
3333   MatCheckPreallocated(mat, 2);
3334   if (!info) {
3335     PetscCall(MatFactorInfoInitialize(&tinfo));
3336     info = &tinfo;
3337   }
3338 
3339   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3340   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3341   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3342   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3343   PetscFunctionReturn(PETSC_SUCCESS);
3344 }
3345 
3346 /*@C
3347    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3348    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3349    `MatCholeskyFactorSymbolic()`.
3350 
3351    Collective
3352 
3353    Input Parameters:
3354 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3355 .  mat - the initial matrix that is to be factored
3356 -  info - options for factorization
3357 
3358    Level: developer
3359 
3360    Note:
3361    Most users should employ the `KSP` interface for linear solvers
3362    instead of working directly with matrix algebra routines such as this.
3363    See, e.g., `KSPCreate()`.
3364 
3365    Developer Note:
3366    The Fortran interface is not autogenerated as the
3367    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3368 
3369 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3370 @*/
3371 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3372 {
3373   MatFactorInfo tinfo;
3374 
3375   PetscFunctionBegin;
3376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3377   PetscValidType(mat, 2);
3378   PetscValidPointer(fact, 1);
3379   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3380   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3381   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3382   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,
3383              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3384   MatCheckPreallocated(mat, 2);
3385   if (!info) {
3386     PetscCall(MatFactorInfoInitialize(&tinfo));
3387     info = &tinfo;
3388   }
3389 
3390   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3391   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3392   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3393   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3394   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3395   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3396   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3397   PetscFunctionReturn(PETSC_SUCCESS);
3398 }
3399 
3400 /*@
3401    MatQRFactor - Performs in-place QR factorization of matrix.
3402 
3403    Collective
3404 
3405    Input Parameters:
3406 +  mat - the matrix
3407 .  col - column permutation
3408 -  info - options for factorization, includes
3409 .vb
3410           fill - expected fill as ratio of original fill.
3411           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3412                    Run with the option -info to determine an optimal value to use
3413 .ve
3414 
3415    Level: developer
3416 
3417    Notes:
3418    Most users should employ the `KSP` interface for linear solvers
3419    instead of working directly with matrix algebra routines such as this.
3420    See, e.g., `KSPCreate()`.
3421 
3422    This changes the state of the matrix to a factored matrix; it cannot be used
3423    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3424 
3425    Developer Note:
3426    The Fortran interface is not autogenerated as the
3427    interface definition cannot be generated correctly [due to MatFactorInfo]
3428 
3429 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3430           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3431 @*/
3432 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3433 {
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3436   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3437   if (info) PetscValidPointer(info, 3);
3438   PetscValidType(mat, 1);
3439   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3440   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3441   MatCheckPreallocated(mat, 1);
3442   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3443   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3444   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3445   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3446   PetscFunctionReturn(PETSC_SUCCESS);
3447 }
3448 
3449 /*@
3450    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3451    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3452 
3453    Collective
3454 
3455    Input Parameters:
3456 +  fact - the factor matrix obtained with `MatGetFactor()`
3457 .  mat - the matrix
3458 .  col - column permutation
3459 -  info - options for factorization, includes
3460 .vb
3461           fill - expected fill as ratio of original fill.
3462           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3463                    Run with the option -info to determine an optimal value to use
3464 .ve
3465 
3466    Level: developer
3467 
3468    Note:
3469    Most users should employ the `KSP` interface for linear solvers
3470    instead of working directly with matrix algebra routines such as this.
3471    See, e.g., `KSPCreate()`.
3472 
3473    Developer Note:
3474    The Fortran interface is not autogenerated as the
3475    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3476 
3477 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3478 @*/
3479 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3480 {
3481   MatFactorInfo tinfo;
3482 
3483   PetscFunctionBegin;
3484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3485   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3486   if (info) PetscValidPointer(info, 4);
3487   PetscValidType(mat, 2);
3488   PetscValidPointer(fact, 1);
3489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3491   MatCheckPreallocated(mat, 2);
3492   if (!info) {
3493     PetscCall(MatFactorInfoInitialize(&tinfo));
3494     info = &tinfo;
3495   }
3496 
3497   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3498   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3499   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3500   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3501   PetscFunctionReturn(PETSC_SUCCESS);
3502 }
3503 
3504 /*@
3505    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3506    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3507 
3508    Collective
3509 
3510    Input Parameters:
3511 +  fact - the factor matrix obtained with `MatGetFactor()`
3512 .  mat - the matrix
3513 -  info - options for factorization
3514 
3515    Level: developer
3516 
3517    Notes:
3518    See `MatQRFactor()` for in-place factorization.
3519 
3520    Most users should employ the `KSP` interface for linear solvers
3521    instead of working directly with matrix algebra routines such as this.
3522    See, e.g., `KSPCreate()`.
3523 
3524    Developer Note:
3525    The Fortran interface is not autogenerated as the
3526    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3527 
3528 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3529 @*/
3530 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3531 {
3532   MatFactorInfo tinfo;
3533 
3534   PetscFunctionBegin;
3535   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3536   PetscValidType(mat, 2);
3537   PetscValidPointer(fact, 1);
3538   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3539   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3540   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,
3541              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3542 
3543   MatCheckPreallocated(mat, 2);
3544   if (!info) {
3545     PetscCall(MatFactorInfoInitialize(&tinfo));
3546     info = &tinfo;
3547   }
3548 
3549   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3550   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3551   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3552   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3553   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3554   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3555   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3556   PetscFunctionReturn(PETSC_SUCCESS);
3557 }
3558 
3559 /*@
3560    MatSolve - Solves A x = b, given a factored matrix.
3561 
3562    Neighbor-wise Collective
3563 
3564    Input Parameters:
3565 +  mat - the factored matrix
3566 -  b - the right-hand-side vector
3567 
3568    Output Parameter:
3569 .  x - the result vector
3570 
3571    Level: developer
3572 
3573    Notes:
3574    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3575    call `MatSolve`(A,x,x).
3576 
3577    Most users should employ the `KSP` interface for linear solvers
3578    instead of working directly with matrix algebra routines such as this.
3579    See, e.g., `KSPCreate()`.
3580 
3581 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3582 @*/
3583 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3584 {
3585   PetscFunctionBegin;
3586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3587   PetscValidType(mat, 1);
3588   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3589   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3590   PetscCheckSameComm(mat, 1, b, 2);
3591   PetscCheckSameComm(mat, 1, x, 3);
3592   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3593   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);
3594   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);
3595   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);
3596   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3597   MatCheckPreallocated(mat, 1);
3598 
3599   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3600   if (mat->factorerrortype) {
3601     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3602     PetscCall(VecSetInf(x));
3603   } else PetscUseTypeMethod(mat, solve, b, x);
3604   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3605   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3606   PetscFunctionReturn(PETSC_SUCCESS);
3607 }
3608 
3609 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3610 {
3611   Vec      b, x;
3612   PetscInt N, i;
3613   PetscErrorCode (*f)(Mat, Vec, Vec);
3614   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3615 
3616   PetscFunctionBegin;
3617   if (A->factorerrortype) {
3618     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3619     PetscCall(MatSetInf(X));
3620     PetscFunctionReturn(PETSC_SUCCESS);
3621   }
3622   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3623   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3624   PetscCall(MatBoundToCPU(A, &Abound));
3625   if (!Abound) {
3626     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3627     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3628   }
3629 #if defined(PETSC_HAVE_CUDA)
3630   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3631   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3632 #elif (PETSC_HAVE_HIP)
3633   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3634   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3635 #endif
3636   PetscCall(MatGetSize(B, NULL, &N));
3637   for (i = 0; i < N; i++) {
3638     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3639     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3640     PetscCall((*f)(A, b, x));
3641     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3642     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3643   }
3644   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3645   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3646   PetscFunctionReturn(PETSC_SUCCESS);
3647 }
3648 
3649 /*@
3650    MatMatSolve - Solves A X = B, given a factored matrix.
3651 
3652    Neighbor-wise Collective
3653 
3654    Input Parameters:
3655 +  A - the factored matrix
3656 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3657 
3658    Output Parameter:
3659 .  X - the result matrix (dense matrix)
3660 
3661    Level: developer
3662 
3663    Note:
3664    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3665    otherwise, `B` and `X` cannot be the same.
3666 
3667 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3668 @*/
3669 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3670 {
3671   PetscFunctionBegin;
3672   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3673   PetscValidType(A, 1);
3674   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3675   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3676   PetscCheckSameComm(A, 1, B, 2);
3677   PetscCheckSameComm(A, 1, X, 3);
3678   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);
3679   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);
3680   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");
3681   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3682   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3683   MatCheckPreallocated(A, 1);
3684 
3685   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3686   if (!A->ops->matsolve) {
3687     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3688     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3689   } else PetscUseTypeMethod(A, matsolve, B, X);
3690   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3691   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3692   PetscFunctionReturn(PETSC_SUCCESS);
3693 }
3694 
3695 /*@
3696    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3697 
3698    Neighbor-wise Collective
3699 
3700    Input Parameters:
3701 +  A - the factored matrix
3702 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3703 
3704    Output Parameter:
3705 .  X - the result matrix (dense matrix)
3706 
3707    Level: developer
3708 
3709    Note:
3710    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3711    call `MatMatSolveTranspose`(A,X,X).
3712 
3713 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3714 @*/
3715 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3716 {
3717   PetscFunctionBegin;
3718   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3719   PetscValidType(A, 1);
3720   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3721   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3722   PetscCheckSameComm(A, 1, B, 2);
3723   PetscCheckSameComm(A, 1, X, 3);
3724   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3725   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);
3726   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);
3727   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);
3728   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");
3729   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3730   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3731   MatCheckPreallocated(A, 1);
3732 
3733   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3734   if (!A->ops->matsolvetranspose) {
3735     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3736     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3737   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3738   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3739   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3740   PetscFunctionReturn(PETSC_SUCCESS);
3741 }
3742 
3743 /*@
3744    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3745 
3746    Neighbor-wise Collective
3747 
3748    Input Parameters:
3749 +  A - the factored matrix
3750 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3751 
3752    Output Parameter:
3753 .  X - the result matrix (dense matrix)
3754 
3755    Level: developer
3756 
3757    Note:
3758    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
3759    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3760 
3761 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3762 @*/
3763 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3764 {
3765   PetscFunctionBegin;
3766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3767   PetscValidType(A, 1);
3768   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3769   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3770   PetscCheckSameComm(A, 1, Bt, 2);
3771   PetscCheckSameComm(A, 1, X, 3);
3772 
3773   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3774   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);
3775   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);
3776   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");
3777   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3778   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3779   MatCheckPreallocated(A, 1);
3780 
3781   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3782   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3783   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3784   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3785   PetscFunctionReturn(PETSC_SUCCESS);
3786 }
3787 
3788 /*@
3789    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3790                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3791 
3792    Neighbor-wise Collective
3793 
3794    Input Parameters:
3795 +  mat - the factored matrix
3796 -  b - the right-hand-side vector
3797 
3798    Output Parameter:
3799 .  x - the result vector
3800 
3801    Level: developer
3802 
3803    Notes:
3804    `MatSolve()` should be used for most applications, as it performs
3805    a forward solve followed by a backward solve.
3806 
3807    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3808    call `MatForwardSolve`(A,x,x).
3809 
3810    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3811    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3812    `MatForwardSolve()` solves U^T*D y = b, and
3813    `MatBackwardSolve()` solves U x = y.
3814    Thus they do not provide a symmetric preconditioner.
3815 
3816 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3817 @*/
3818 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3819 {
3820   PetscFunctionBegin;
3821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3822   PetscValidType(mat, 1);
3823   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3824   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3825   PetscCheckSameComm(mat, 1, b, 2);
3826   PetscCheckSameComm(mat, 1, x, 3);
3827   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3828   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);
3829   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);
3830   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);
3831   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3832   MatCheckPreallocated(mat, 1);
3833 
3834   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3835   PetscUseTypeMethod(mat, forwardsolve, b, x);
3836   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3837   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3838   PetscFunctionReturn(PETSC_SUCCESS);
3839 }
3840 
3841 /*@
3842    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3843                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3844 
3845    Neighbor-wise Collective
3846 
3847    Input Parameters:
3848 +  mat - the factored matrix
3849 -  b - the right-hand-side vector
3850 
3851    Output Parameter:
3852 .  x - the result vector
3853 
3854    Level: developer
3855 
3856    Notes:
3857    `MatSolve()` should be used for most applications, as it performs
3858    a forward solve followed by a backward solve.
3859 
3860    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3861    call `MatBackwardSolve`(A,x,x).
3862 
3863    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3864    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3865    `MatForwardSolve()` solves U^T*D y = b, and
3866    `MatBackwardSolve()` solves U x = y.
3867    Thus they do not provide a symmetric preconditioner.
3868 
3869 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3870 @*/
3871 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3872 {
3873   PetscFunctionBegin;
3874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3875   PetscValidType(mat, 1);
3876   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3877   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3878   PetscCheckSameComm(mat, 1, b, 2);
3879   PetscCheckSameComm(mat, 1, x, 3);
3880   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3881   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);
3882   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);
3883   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);
3884   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3885   MatCheckPreallocated(mat, 1);
3886 
3887   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3888   PetscUseTypeMethod(mat, backwardsolve, b, x);
3889   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3890   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3891   PetscFunctionReturn(PETSC_SUCCESS);
3892 }
3893 
3894 /*@
3895    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3896 
3897    Neighbor-wise Collective
3898 
3899    Input Parameters:
3900 +  mat - the factored matrix
3901 .  b - the right-hand-side vector
3902 -  y - the vector to be added to
3903 
3904    Output Parameter:
3905 .  x - the result vector
3906 
3907    Level: developer
3908 
3909    Note:
3910    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3911    call `MatSolveAdd`(A,x,y,x).
3912 
3913 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3914 @*/
3915 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3916 {
3917   PetscScalar one = 1.0;
3918   Vec         tmp;
3919 
3920   PetscFunctionBegin;
3921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3922   PetscValidType(mat, 1);
3923   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3924   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3925   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3926   PetscCheckSameComm(mat, 1, b, 2);
3927   PetscCheckSameComm(mat, 1, y, 3);
3928   PetscCheckSameComm(mat, 1, x, 4);
3929   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3930   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);
3931   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);
3932   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);
3933   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);
3934   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);
3935   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3936   MatCheckPreallocated(mat, 1);
3937 
3938   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3939   if (mat->factorerrortype) {
3940     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3941     PetscCall(VecSetInf(x));
3942   } else if (mat->ops->solveadd) {
3943     PetscUseTypeMethod(mat, solveadd, b, y, x);
3944   } else {
3945     /* do the solve then the add manually */
3946     if (x != y) {
3947       PetscCall(MatSolve(mat, b, x));
3948       PetscCall(VecAXPY(x, one, y));
3949     } else {
3950       PetscCall(VecDuplicate(x, &tmp));
3951       PetscCall(VecCopy(x, tmp));
3952       PetscCall(MatSolve(mat, b, x));
3953       PetscCall(VecAXPY(x, one, tmp));
3954       PetscCall(VecDestroy(&tmp));
3955     }
3956   }
3957   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3958   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3959   PetscFunctionReturn(PETSC_SUCCESS);
3960 }
3961 
3962 /*@
3963    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3964 
3965    Neighbor-wise Collective
3966 
3967    Input Parameters:
3968 +  mat - the factored matrix
3969 -  b - the right-hand-side vector
3970 
3971    Output Parameter:
3972 .  x - the result vector
3973 
3974    Level: developer
3975 
3976    Notes:
3977    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3978    call `MatSolveTranspose`(A,x,x).
3979 
3980    Most users should employ the `KSP` interface for linear solvers
3981    instead of working directly with matrix algebra routines such as this.
3982    See, e.g., `KSPCreate()`.
3983 
3984 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3985 @*/
3986 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3987 {
3988   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3989 
3990   PetscFunctionBegin;
3991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3992   PetscValidType(mat, 1);
3993   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3994   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3995   PetscCheckSameComm(mat, 1, b, 2);
3996   PetscCheckSameComm(mat, 1, x, 3);
3997   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3998   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);
3999   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);
4000   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4001   MatCheckPreallocated(mat, 1);
4002   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4003   if (mat->factorerrortype) {
4004     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4005     PetscCall(VecSetInf(x));
4006   } else {
4007     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4008     PetscCall((*f)(mat, b, x));
4009   }
4010   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4011   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4012   PetscFunctionReturn(PETSC_SUCCESS);
4013 }
4014 
4015 /*@
4016    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4017                       factored matrix.
4018 
4019    Neighbor-wise Collective
4020 
4021    Input Parameters:
4022 +  mat - the factored matrix
4023 .  b - the right-hand-side vector
4024 -  y - the vector to be added to
4025 
4026    Output Parameter:
4027 .  x - the result vector
4028 
4029    Level: developer
4030 
4031    Note:
4032    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4033    call `MatSolveTransposeAdd`(A,x,y,x).
4034 
4035 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4036 @*/
4037 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4038 {
4039   PetscScalar one = 1.0;
4040   Vec         tmp;
4041   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4042 
4043   PetscFunctionBegin;
4044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4045   PetscValidType(mat, 1);
4046   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4047   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4048   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4049   PetscCheckSameComm(mat, 1, b, 2);
4050   PetscCheckSameComm(mat, 1, y, 3);
4051   PetscCheckSameComm(mat, 1, x, 4);
4052   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4053   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);
4054   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);
4055   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);
4056   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);
4057   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4058   MatCheckPreallocated(mat, 1);
4059 
4060   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4061   if (mat->factorerrortype) {
4062     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4063     PetscCall(VecSetInf(x));
4064   } else if (f) {
4065     PetscCall((*f)(mat, b, y, x));
4066   } else {
4067     /* do the solve then the add manually */
4068     if (x != y) {
4069       PetscCall(MatSolveTranspose(mat, b, x));
4070       PetscCall(VecAXPY(x, one, y));
4071     } else {
4072       PetscCall(VecDuplicate(x, &tmp));
4073       PetscCall(VecCopy(x, tmp));
4074       PetscCall(MatSolveTranspose(mat, b, x));
4075       PetscCall(VecAXPY(x, one, tmp));
4076       PetscCall(VecDestroy(&tmp));
4077     }
4078   }
4079   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4080   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4081   PetscFunctionReturn(PETSC_SUCCESS);
4082 }
4083 
4084 /*@
4085    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4086 
4087    Neighbor-wise Collective
4088 
4089    Input Parameters:
4090 +  mat - the matrix
4091 .  b - the right hand side
4092 .  omega - the relaxation factor
4093 .  flag - flag indicating the type of SOR (see below)
4094 .  shift -  diagonal shift
4095 .  its - the number of iterations
4096 -  lits - the number of local iterations
4097 
4098    Output Parameter:
4099 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4100 
4101    SOR Flags:
4102 +     `SOR_FORWARD_SWEEP` - forward SOR
4103 .     `SOR_BACKWARD_SWEEP` - backward SOR
4104 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4105 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4106 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4107 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4108 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4109 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4110          upper/lower triangular part of matrix to
4111          vector (with omega)
4112 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4113 
4114    Level: developer
4115 
4116    Notes:
4117    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4118    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4119    on each processor.
4120 
4121    Application programmers will not generally use `MatSOR()` directly,
4122    but instead will employ the `KSP`/`PC` interface.
4123 
4124    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4125 
4126    Most users should employ the `KSP` interface for linear solvers
4127    instead of working directly with matrix algebra routines such as this.
4128    See, e.g., `KSPCreate()`.
4129 
4130    Vectors `x` and `b` CANNOT be the same
4131 
4132    The flags are implemented as bitwise inclusive or operations.
4133    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4134    to specify a zero initial guess for SSOR.
4135 
4136    Developer Note:
4137    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4138 
4139 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4140 @*/
4141 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4142 {
4143   PetscFunctionBegin;
4144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4145   PetscValidType(mat, 1);
4146   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4147   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4148   PetscCheckSameComm(mat, 1, b, 2);
4149   PetscCheckSameComm(mat, 1, x, 8);
4150   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4151   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4152   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);
4153   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);
4154   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);
4155   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4156   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4157   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4158 
4159   MatCheckPreallocated(mat, 1);
4160   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4161   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4162   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4163   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4164   PetscFunctionReturn(PETSC_SUCCESS);
4165 }
4166 
4167 /*
4168       Default matrix copy routine.
4169 */
4170 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4171 {
4172   PetscInt           i, rstart = 0, rend = 0, nz;
4173   const PetscInt    *cwork;
4174   const PetscScalar *vwork;
4175 
4176   PetscFunctionBegin;
4177   if (B->assembled) PetscCall(MatZeroEntries(B));
4178   if (str == SAME_NONZERO_PATTERN) {
4179     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4180     for (i = rstart; i < rend; i++) {
4181       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4182       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4183       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4184     }
4185   } else {
4186     PetscCall(MatAYPX(B, 0.0, A, str));
4187   }
4188   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4189   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4190   PetscFunctionReturn(PETSC_SUCCESS);
4191 }
4192 
4193 /*@
4194    MatCopy - Copies a matrix to another matrix.
4195 
4196    Collective
4197 
4198    Input Parameters:
4199 +  A - the matrix
4200 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4201 
4202    Output Parameter:
4203 .  B - where the copy is put
4204 
4205    Level: intermediate
4206 
4207    Notes:
4208    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4209 
4210    `MatCopy()` copies the matrix entries of a matrix to another existing
4211    matrix (after first zeroing the second matrix).  A related routine is
4212    `MatConvert()`, which first creates a new matrix and then copies the data.
4213 
4214 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4215 @*/
4216 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4217 {
4218   PetscInt i;
4219 
4220   PetscFunctionBegin;
4221   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4222   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4223   PetscValidType(A, 1);
4224   PetscValidType(B, 2);
4225   PetscCheckSameComm(A, 1, B, 2);
4226   MatCheckPreallocated(B, 2);
4227   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4228   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4229   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,
4230              A->cmap->N, B->cmap->N);
4231   MatCheckPreallocated(A, 1);
4232   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4233 
4234   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4235   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4236   else PetscCall(MatCopy_Basic(A, B, str));
4237 
4238   B->stencil.dim = A->stencil.dim;
4239   B->stencil.noc = A->stencil.noc;
4240   for (i = 0; i <= A->stencil.dim; i++) {
4241     B->stencil.dims[i]   = A->stencil.dims[i];
4242     B->stencil.starts[i] = A->stencil.starts[i];
4243   }
4244 
4245   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4246   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4247   PetscFunctionReturn(PETSC_SUCCESS);
4248 }
4249 
4250 /*@C
4251    MatConvert - Converts a matrix to another matrix, either of the same
4252    or different type.
4253 
4254    Collective
4255 
4256    Input Parameters:
4257 +  mat - the matrix
4258 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4259    same type as the original matrix.
4260 -  reuse - denotes if the destination matrix is to be created or reused.
4261    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
4262    `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).
4263 
4264    Output Parameter:
4265 .  M - pointer to place new matrix
4266 
4267    Level: intermediate
4268 
4269    Notes:
4270    `MatConvert()` first creates a new matrix and then copies the data from
4271    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4272    entries of one matrix to another already existing matrix context.
4273 
4274    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4275    the MPI communicator of the generated matrix is always the same as the communicator
4276    of the input matrix.
4277 
4278 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4279 @*/
4280 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4281 {
4282   PetscBool  sametype, issame, flg;
4283   PetscBool3 issymmetric, ishermitian;
4284   char       convname[256], mtype[256];
4285   Mat        B;
4286 
4287   PetscFunctionBegin;
4288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4289   PetscValidType(mat, 1);
4290   PetscValidPointer(M, 4);
4291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4293   MatCheckPreallocated(mat, 1);
4294 
4295   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4296   if (flg) newtype = mtype;
4297 
4298   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4299   PetscCall(PetscStrcmp(newtype, "same", &issame));
4300   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4301   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");
4302 
4303   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4304     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4305     PetscFunctionReturn(PETSC_SUCCESS);
4306   }
4307 
4308   /* Cache Mat options because some converters use MatHeaderReplace  */
4309   issymmetric = mat->symmetric;
4310   ishermitian = mat->hermitian;
4311 
4312   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4313     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4314     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4315   } else {
4316     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4317     const char *prefix[3]                                 = {"seq", "mpi", ""};
4318     PetscInt    i;
4319     /*
4320        Order of precedence:
4321        0) See if newtype is a superclass of the current matrix.
4322        1) See if a specialized converter is known to the current matrix.
4323        2) See if a specialized converter is known to the desired matrix class.
4324        3) See if a good general converter is registered for the desired class
4325           (as of 6/27/03 only MATMPIADJ falls into this category).
4326        4) See if a good general converter is known for the current matrix.
4327        5) Use a really basic converter.
4328     */
4329 
4330     /* 0) See if newtype is a superclass of the current matrix.
4331           i.e mat is mpiaij and newtype is aij */
4332     for (i = 0; i < 2; i++) {
4333       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4334       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4335       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4336       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4337       if (flg) {
4338         if (reuse == MAT_INPLACE_MATRIX) {
4339           PetscCall(PetscInfo(mat, "Early return\n"));
4340           PetscFunctionReturn(PETSC_SUCCESS);
4341         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4342           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4343           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4344           PetscFunctionReturn(PETSC_SUCCESS);
4345         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4346           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4347           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4348           PetscFunctionReturn(PETSC_SUCCESS);
4349         }
4350       }
4351     }
4352     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4353     for (i = 0; i < 3; i++) {
4354       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4355       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4357       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4358       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4360       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4361       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4362       if (conv) goto foundconv;
4363     }
4364 
4365     /* 2)  See if a specialized converter is known to the desired matrix class. */
4366     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4367     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4368     PetscCall(MatSetType(B, newtype));
4369     for (i = 0; i < 3; i++) {
4370       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4371       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4372       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4376       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4377       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4378       if (conv) {
4379         PetscCall(MatDestroy(&B));
4380         goto foundconv;
4381       }
4382     }
4383 
4384     /* 3) See if a good general converter is registered for the desired class */
4385     conv = B->ops->convertfrom;
4386     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4387     PetscCall(MatDestroy(&B));
4388     if (conv) goto foundconv;
4389 
4390     /* 4) See if a good general converter is known for the current matrix */
4391     if (mat->ops->convert) conv = mat->ops->convert;
4392     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4393     if (conv) goto foundconv;
4394 
4395     /* 5) Use a really basic converter. */
4396     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4397     conv = MatConvert_Basic;
4398 
4399   foundconv:
4400     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4401     PetscCall((*conv)(mat, newtype, reuse, M));
4402     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4403       /* the block sizes must be same if the mappings are copied over */
4404       (*M)->rmap->bs = mat->rmap->bs;
4405       (*M)->cmap->bs = mat->cmap->bs;
4406       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4407       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4408       (*M)->rmap->mapping = mat->rmap->mapping;
4409       (*M)->cmap->mapping = mat->cmap->mapping;
4410     }
4411     (*M)->stencil.dim = mat->stencil.dim;
4412     (*M)->stencil.noc = mat->stencil.noc;
4413     for (i = 0; i <= mat->stencil.dim; i++) {
4414       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4415       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4416     }
4417     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4418   }
4419   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4420 
4421   /* Copy Mat options */
4422   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4423   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4424   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4425   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4426   PetscFunctionReturn(PETSC_SUCCESS);
4427 }
4428 
4429 /*@C
4430    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4431 
4432    Not Collective
4433 
4434    Input Parameter:
4435 .  mat - the matrix, must be a factored matrix
4436 
4437    Output Parameter:
4438 .   type - the string name of the package (do not free this string)
4439 
4440    Level: intermediate
4441 
4442    Fortran Note:
4443    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4444 
4445 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4446 @*/
4447 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4448 {
4449   PetscErrorCode (*conv)(Mat, MatSolverType *);
4450 
4451   PetscFunctionBegin;
4452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4453   PetscValidType(mat, 1);
4454   PetscValidPointer(type, 2);
4455   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4456   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4457   if (conv) PetscCall((*conv)(mat, type));
4458   else *type = MATSOLVERPETSC;
4459   PetscFunctionReturn(PETSC_SUCCESS);
4460 }
4461 
4462 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4463 struct _MatSolverTypeForSpecifcType {
4464   MatType mtype;
4465   /* no entry for MAT_FACTOR_NONE */
4466   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4467   MatSolverTypeForSpecifcType next;
4468 };
4469 
4470 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4471 struct _MatSolverTypeHolder {
4472   char                       *name;
4473   MatSolverTypeForSpecifcType handlers;
4474   MatSolverTypeHolder         next;
4475 };
4476 
4477 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4478 
4479 /*@C
4480    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4481 
4482    Input Parameters:
4483 +    package - name of the package, for example petsc or superlu
4484 .    mtype - the matrix type that works with this package
4485 .    ftype - the type of factorization supported by the package
4486 -    createfactor - routine that will create the factored matrix ready to be used
4487 
4488     Level: developer
4489 
4490 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4491 @*/
4492 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4493 {
4494   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4495   PetscBool                   flg;
4496   MatSolverTypeForSpecifcType inext, iprev = NULL;
4497 
4498   PetscFunctionBegin;
4499   PetscCall(MatInitializePackage());
4500   if (!next) {
4501     PetscCall(PetscNew(&MatSolverTypeHolders));
4502     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4503     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4504     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4505     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4506     PetscFunctionReturn(PETSC_SUCCESS);
4507   }
4508   while (next) {
4509     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4510     if (flg) {
4511       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4512       inext = next->handlers;
4513       while (inext) {
4514         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4515         if (flg) {
4516           inext->createfactor[(int)ftype - 1] = createfactor;
4517           PetscFunctionReturn(PETSC_SUCCESS);
4518         }
4519         iprev = inext;
4520         inext = inext->next;
4521       }
4522       PetscCall(PetscNew(&iprev->next));
4523       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4524       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4525       PetscFunctionReturn(PETSC_SUCCESS);
4526     }
4527     prev = next;
4528     next = next->next;
4529   }
4530   PetscCall(PetscNew(&prev->next));
4531   PetscCall(PetscStrallocpy(package, &prev->next->name));
4532   PetscCall(PetscNew(&prev->next->handlers));
4533   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4534   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4535   PetscFunctionReturn(PETSC_SUCCESS);
4536 }
4537 
4538 /*@C
4539    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4540 
4541    Input Parameters:
4542 +    type - name of the package, for example petsc or superlu
4543 .    ftype - the type of factorization supported by the type
4544 -    mtype - the matrix type that works with this type
4545 
4546    Output Parameters:
4547 +   foundtype - `PETSC_TRUE` if the type was registered
4548 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4549 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4550 
4551     Level: developer
4552 
4553 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4554 @*/
4555 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4556 {
4557   MatSolverTypeHolder         next = MatSolverTypeHolders;
4558   PetscBool                   flg;
4559   MatSolverTypeForSpecifcType inext;
4560 
4561   PetscFunctionBegin;
4562   if (foundtype) *foundtype = PETSC_FALSE;
4563   if (foundmtype) *foundmtype = PETSC_FALSE;
4564   if (createfactor) *createfactor = NULL;
4565 
4566   if (type) {
4567     while (next) {
4568       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4569       if (flg) {
4570         if (foundtype) *foundtype = PETSC_TRUE;
4571         inext = next->handlers;
4572         while (inext) {
4573           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4574           if (flg) {
4575             if (foundmtype) *foundmtype = PETSC_TRUE;
4576             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4577             PetscFunctionReturn(PETSC_SUCCESS);
4578           }
4579           inext = inext->next;
4580         }
4581       }
4582       next = next->next;
4583     }
4584   } else {
4585     while (next) {
4586       inext = next->handlers;
4587       while (inext) {
4588         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4589         if (flg && inext->createfactor[(int)ftype - 1]) {
4590           if (foundtype) *foundtype = PETSC_TRUE;
4591           if (foundmtype) *foundmtype = PETSC_TRUE;
4592           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4593           PetscFunctionReturn(PETSC_SUCCESS);
4594         }
4595         inext = inext->next;
4596       }
4597       next = next->next;
4598     }
4599     /* try with base classes inext->mtype */
4600     next = MatSolverTypeHolders;
4601     while (next) {
4602       inext = next->handlers;
4603       while (inext) {
4604         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4605         if (flg && inext->createfactor[(int)ftype - 1]) {
4606           if (foundtype) *foundtype = PETSC_TRUE;
4607           if (foundmtype) *foundmtype = PETSC_TRUE;
4608           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4609           PetscFunctionReturn(PETSC_SUCCESS);
4610         }
4611         inext = inext->next;
4612       }
4613       next = next->next;
4614     }
4615   }
4616   PetscFunctionReturn(PETSC_SUCCESS);
4617 }
4618 
4619 PetscErrorCode MatSolverTypeDestroy(void)
4620 {
4621   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4622   MatSolverTypeForSpecifcType inext, iprev;
4623 
4624   PetscFunctionBegin;
4625   while (next) {
4626     PetscCall(PetscFree(next->name));
4627     inext = next->handlers;
4628     while (inext) {
4629       PetscCall(PetscFree(inext->mtype));
4630       iprev = inext;
4631       inext = inext->next;
4632       PetscCall(PetscFree(iprev));
4633     }
4634     prev = next;
4635     next = next->next;
4636     PetscCall(PetscFree(prev));
4637   }
4638   MatSolverTypeHolders = NULL;
4639   PetscFunctionReturn(PETSC_SUCCESS);
4640 }
4641 
4642 /*@C
4643    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4644 
4645    Logically Collective
4646 
4647    Input Parameter:
4648 .  mat - the matrix
4649 
4650    Output Parameter:
4651 .  flg - `PETSC_TRUE` if uses the ordering
4652 
4653    Level: developer
4654 
4655    Note:
4656    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4657    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4658 
4659 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4660 @*/
4661 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4662 {
4663   PetscFunctionBegin;
4664   *flg = mat->canuseordering;
4665   PetscFunctionReturn(PETSC_SUCCESS);
4666 }
4667 
4668 /*@C
4669    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4670 
4671    Logically Collective
4672 
4673    Input Parameters:
4674 +  mat - the matrix obtained with `MatGetFactor()`
4675 -  ftype - the factorization type to be used
4676 
4677    Output Parameter:
4678 .  otype - the preferred ordering type
4679 
4680    Level: developer
4681 
4682 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4683 @*/
4684 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4685 {
4686   PetscFunctionBegin;
4687   *otype = mat->preferredordering[ftype];
4688   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4689   PetscFunctionReturn(PETSC_SUCCESS);
4690 }
4691 
4692 /*@C
4693    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4694 
4695    Collective
4696 
4697    Input Parameters:
4698 +  mat - the matrix
4699 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4700 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4701 
4702    Output Parameter:
4703 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4704 
4705    Options Database Key:
4706 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4707                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4708 
4709    Level: intermediate
4710 
4711    Notes:
4712      Users usually access the factorization solvers via `KSP`
4713 
4714       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4715      such as pastix, superlu, mumps etc.
4716 
4717       PETSc must have been ./configure to use the external solver, using the option --download-package
4718 
4719       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4720       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4721       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4722 
4723    Developer Note:
4724       This should actually be called `MatCreateFactor()` since it creates a new factor object
4725 
4726 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4727           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4728 @*/
4729 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4730 {
4731   PetscBool foundtype, foundmtype;
4732   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4733 
4734   PetscFunctionBegin;
4735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4736   PetscValidType(mat, 1);
4737 
4738   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4739   MatCheckPreallocated(mat, 1);
4740 
4741   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4742   if (!foundtype) {
4743     if (type) {
4744       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],
4745               ((PetscObject)mat)->type_name, type);
4746     } else {
4747       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);
4748     }
4749   }
4750   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4751   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);
4752 
4753   PetscCall((*conv)(mat, ftype, f));
4754   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4755   PetscFunctionReturn(PETSC_SUCCESS);
4756 }
4757 
4758 /*@C
4759    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4760 
4761    Not Collective
4762 
4763    Input Parameters:
4764 +  mat - the matrix
4765 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4766 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4767 
4768    Output Parameter:
4769 .    flg - PETSC_TRUE if the factorization is available
4770 
4771    Level: intermediate
4772 
4773    Notes:
4774       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4775      such as pastix, superlu, mumps etc.
4776 
4777       PETSc must have been ./configure to use the external solver, using the option --download-package
4778 
4779    Developer Note:
4780       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4781 
4782 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4783           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4784 @*/
4785 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4786 {
4787   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4788 
4789   PetscFunctionBegin;
4790   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4791   PetscValidType(mat, 1);
4792   PetscValidBoolPointer(flg, 4);
4793 
4794   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4795   MatCheckPreallocated(mat, 1);
4796 
4797   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4798   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4799   PetscFunctionReturn(PETSC_SUCCESS);
4800 }
4801 
4802 /*@
4803    MatDuplicate - Duplicates a matrix including the non-zero structure.
4804 
4805    Collective
4806 
4807    Input Parameters:
4808 +  mat - the matrix
4809 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4810         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4811 
4812    Output Parameter:
4813 .  M - pointer to place new matrix
4814 
4815    Level: intermediate
4816 
4817    Notes:
4818     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4819 
4820     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.
4821 
4822     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
4823     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4824     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4825 
4826 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4827 @*/
4828 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4829 {
4830   Mat         B;
4831   VecType     vtype;
4832   PetscInt    i;
4833   PetscObject dm;
4834   void (*viewf)(void);
4835 
4836   PetscFunctionBegin;
4837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4838   PetscValidType(mat, 1);
4839   PetscValidPointer(M, 3);
4840   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4841   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4842   MatCheckPreallocated(mat, 1);
4843 
4844   *M = NULL;
4845   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4846   PetscUseTypeMethod(mat, duplicate, op, M);
4847   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4848   B = *M;
4849 
4850   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4851   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4852   PetscCall(MatGetVecType(mat, &vtype));
4853   PetscCall(MatSetVecType(B, vtype));
4854 
4855   B->stencil.dim = mat->stencil.dim;
4856   B->stencil.noc = mat->stencil.noc;
4857   for (i = 0; i <= mat->stencil.dim; i++) {
4858     B->stencil.dims[i]   = mat->stencil.dims[i];
4859     B->stencil.starts[i] = mat->stencil.starts[i];
4860   }
4861 
4862   B->nooffproczerorows = mat->nooffproczerorows;
4863   B->nooffprocentries  = mat->nooffprocentries;
4864 
4865   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4866   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
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   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5256   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5257   PetscCall((*A->ops->transposesymbolic)(A, B));
5258   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5259 
5260   PetscCall(MatTransposeSetPrecursor(A, *B));
5261   PetscFunctionReturn(PETSC_SUCCESS);
5262 }
5263 
5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5265 {
5266   PetscContainer  rB;
5267   MatParentState *rb;
5268 
5269   PetscFunctionBegin;
5270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5271   PetscValidType(A, 1);
5272   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5273   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5274   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5275   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5276   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5277   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5278   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5279   PetscFunctionReturn(PETSC_SUCCESS);
5280 }
5281 
5282 /*@
5283    MatIsTranspose - Test whether a matrix is another one's transpose,
5284         or its own, in which case it tests symmetry.
5285 
5286    Collective
5287 
5288    Input Parameters:
5289 +  A - the matrix to test
5290 .  B - the matrix to test against, this can equal the first parameter
5291 -  tol - tolerance, differences between entries smaller than this are counted as zero
5292 
5293    Output Parameter:
5294 .  flg - the result
5295 
5296    Level: intermediate
5297 
5298    Notes:
5299    Only available for `MATAIJ` matrices.
5300 
5301    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5302    test involves parallel copies of the block-offdiagonal parts of the matrix.
5303 
5304 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5305 @*/
5306 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5307 {
5308   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5309 
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5312   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5313   PetscValidBoolPointer(flg, 4);
5314   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5315   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5316   *flg = PETSC_FALSE;
5317   if (f && g) {
5318     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5319     PetscCall((*f)(A, B, tol, flg));
5320   } else {
5321     MatType mattype;
5322 
5323     PetscCall(MatGetType(f ? B : A, &mattype));
5324     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5325   }
5326   PetscFunctionReturn(PETSC_SUCCESS);
5327 }
5328 
5329 /*@
5330    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5331 
5332    Collective
5333 
5334    Input Parameters:
5335 +  mat - the matrix to transpose and complex conjugate
5336 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5337 
5338    Output Parameter:
5339 .  B - the Hermitian transpose
5340 
5341    Level: intermediate
5342 
5343 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5344 @*/
5345 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5346 {
5347   PetscFunctionBegin;
5348   PetscCall(MatTranspose(mat, reuse, B));
5349 #if defined(PETSC_USE_COMPLEX)
5350   PetscCall(MatConjugate(*B));
5351 #endif
5352   PetscFunctionReturn(PETSC_SUCCESS);
5353 }
5354 
5355 /*@
5356    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5357 
5358    Collective
5359 
5360    Input Parameters:
5361 +  A - the matrix to test
5362 .  B - the matrix to test against, this can equal the first parameter
5363 -  tol - tolerance, differences between entries smaller than this are counted as zero
5364 
5365    Output Parameter:
5366 .  flg - the result
5367 
5368    Level: intermediate
5369 
5370    Notes:
5371    Only available for `MATAIJ` matrices.
5372 
5373    The sequential algorithm
5374    has a running time of the order of the number of nonzeros; the parallel
5375    test involves parallel copies of the block-offdiagonal parts of the matrix.
5376 
5377 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5378 @*/
5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5380 {
5381   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5382 
5383   PetscFunctionBegin;
5384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5385   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5386   PetscValidBoolPointer(flg, 4);
5387   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5388   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5389   if (f && g) {
5390     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5391     PetscCall((*f)(A, B, tol, flg));
5392   }
5393   PetscFunctionReturn(PETSC_SUCCESS);
5394 }
5395 
5396 /*@
5397    MatPermute - Creates a new matrix with rows and columns permuted from the
5398    original.
5399 
5400    Collective
5401 
5402    Input Parameters:
5403 +  mat - the matrix to permute
5404 .  row - row permutation, each processor supplies only the permutation for its rows
5405 -  col - column permutation, each processor supplies only the permutation for its columns
5406 
5407    Output Parameter:
5408 .  B - the permuted matrix
5409 
5410    Level: advanced
5411 
5412    Note:
5413    The index sets map from row/col of permuted matrix to row/col of original matrix.
5414    The index sets should be on the same communicator as mat and have the same local sizes.
5415 
5416    Developer Note:
5417      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5418      exploit the fact that row and col are permutations, consider implementing the
5419      more general `MatCreateSubMatrix()` instead.
5420 
5421 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5422 @*/
5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5424 {
5425   PetscFunctionBegin;
5426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5427   PetscValidType(mat, 1);
5428   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5429   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5430   PetscValidPointer(B, 4);
5431   PetscCheckSameComm(mat, 1, row, 2);
5432   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5435   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5436   MatCheckPreallocated(mat, 1);
5437 
5438   if (mat->ops->permute) {
5439     PetscUseTypeMethod(mat, permute, row, col, B);
5440     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5441   } else {
5442     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5443   }
5444   PetscFunctionReturn(PETSC_SUCCESS);
5445 }
5446 
5447 /*@
5448    MatEqual - Compares two matrices.
5449 
5450    Collective
5451 
5452    Input Parameters:
5453 +  A - the first matrix
5454 -  B - the second matrix
5455 
5456    Output Parameter:
5457 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5458 
5459    Level: intermediate
5460 
5461 .seealso: [](chapter_matrices), `Mat`
5462 @*/
5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5464 {
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5467   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5468   PetscValidType(A, 1);
5469   PetscValidType(B, 2);
5470   PetscValidBoolPointer(flg, 3);
5471   PetscCheckSameComm(A, 1, B, 2);
5472   MatCheckPreallocated(A, 1);
5473   MatCheckPreallocated(B, 2);
5474   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5476   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,
5477              B->cmap->N);
5478   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5479     PetscUseTypeMethod(A, equal, B, flg);
5480   } else {
5481     PetscCall(MatMultEqual(A, B, 10, flg));
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5488    matrices that are stored as vectors.  Either of the two scaling
5489    matrices can be `NULL`.
5490 
5491    Collective
5492 
5493    Input Parameters:
5494 +  mat - the matrix to be scaled
5495 .  l - the left scaling vector (or `NULL`)
5496 -  r - the right scaling vector (or `NULL`)
5497 
5498    Level: intermediate
5499 
5500    Note:
5501    `MatDiagonalScale()` computes A = LAR, where
5502    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5503    The L scales the rows of the matrix, the R scales the columns of the matrix.
5504 
5505 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5506 @*/
5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5511   PetscValidType(mat, 1);
5512   if (l) {
5513     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5514     PetscCheckSameComm(mat, 1, l, 2);
5515   }
5516   if (r) {
5517     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5518     PetscCheckSameComm(mat, 1, r, 3);
5519   }
5520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5522   MatCheckPreallocated(mat, 1);
5523   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5524 
5525   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5526   PetscUseTypeMethod(mat, diagonalscale, l, r);
5527   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5528   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5529   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5530   PetscFunctionReturn(PETSC_SUCCESS);
5531 }
5532 
5533 /*@
5534     MatScale - Scales all elements of a matrix by a given number.
5535 
5536     Logically Collective
5537 
5538     Input Parameters:
5539 +   mat - the matrix to be scaled
5540 -   a  - the scaling value
5541 
5542     Level: intermediate
5543 
5544 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5545 @*/
5546 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5547 {
5548   PetscFunctionBegin;
5549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5550   PetscValidType(mat, 1);
5551   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5554   PetscValidLogicalCollectiveScalar(mat, a, 2);
5555   MatCheckPreallocated(mat, 1);
5556 
5557   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5558   if (a != (PetscScalar)1.0) {
5559     PetscUseTypeMethod(mat, scale, a);
5560     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5561   }
5562   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5563   PetscFunctionReturn(PETSC_SUCCESS);
5564 }
5565 
5566 /*@
5567    MatNorm - Calculates various norms of a matrix.
5568 
5569    Collective
5570 
5571    Input Parameters:
5572 +  mat - the matrix
5573 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5574 
5575    Output Parameter:
5576 .  nrm - the resulting norm
5577 
5578    Level: intermediate
5579 
5580 .seealso: [](chapter_matrices), `Mat`
5581 @*/
5582 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5583 {
5584   PetscFunctionBegin;
5585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5586   PetscValidType(mat, 1);
5587   PetscValidRealPointer(nrm, 3);
5588 
5589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5591   MatCheckPreallocated(mat, 1);
5592 
5593   PetscUseTypeMethod(mat, norm, type, nrm);
5594   PetscFunctionReturn(PETSC_SUCCESS);
5595 }
5596 
5597 /*
5598      This variable is used to prevent counting of MatAssemblyBegin() that
5599    are called from within a MatAssemblyEnd().
5600 */
5601 static PetscInt MatAssemblyEnd_InUse = 0;
5602 /*@
5603    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5604    be called after completing all calls to `MatSetValues()`.
5605 
5606    Collective
5607 
5608    Input Parameters:
5609 +  mat - the matrix
5610 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5611 
5612    Level: beginner
5613 
5614    Notes:
5615    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5616    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5617 
5618    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5619    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5620    using the matrix.
5621 
5622    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5623    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
5624    a global collective operation requiring all processes that share the matrix.
5625 
5626    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5627    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5628    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5629 
5630 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5631 @*/
5632 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5633 {
5634   PetscFunctionBegin;
5635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5636   PetscValidType(mat, 1);
5637   MatCheckPreallocated(mat, 1);
5638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5639   if (mat->assembled) {
5640     mat->was_assembled = PETSC_TRUE;
5641     mat->assembled     = PETSC_FALSE;
5642   }
5643 
5644   if (!MatAssemblyEnd_InUse) {
5645     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5646     PetscTryTypeMethod(mat, assemblybegin, type);
5647     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5648   } else PetscTryTypeMethod(mat, assemblybegin, type);
5649   PetscFunctionReturn(PETSC_SUCCESS);
5650 }
5651 
5652 /*@
5653    MatAssembled - Indicates if a matrix has been assembled and is ready for
5654      use; for example, in matrix-vector product.
5655 
5656    Not Collective
5657 
5658    Input Parameter:
5659 .  mat - the matrix
5660 
5661    Output Parameter:
5662 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5663 
5664    Level: advanced
5665 
5666 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5667 @*/
5668 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5669 {
5670   PetscFunctionBegin;
5671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5672   PetscValidBoolPointer(assembled, 2);
5673   *assembled = mat->assembled;
5674   PetscFunctionReturn(PETSC_SUCCESS);
5675 }
5676 
5677 /*@
5678    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5679    be called after `MatAssemblyBegin()`.
5680 
5681    Collective
5682 
5683    Input Parameters:
5684 +  mat - the matrix
5685 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5686 
5687    Options Database Keys:
5688 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5689 .  -mat_view ::ascii_info_detail - Prints more detailed info
5690 .  -mat_view - Prints matrix in ASCII format
5691 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5692 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5693 .  -display <name> - Sets display name (default is host)
5694 .  -draw_pause <sec> - Sets number of seconds to pause after display
5695 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5696 .  -viewer_socket_machine <machine> - Machine to use for socket
5697 .  -viewer_socket_port <port> - Port number to use for socket
5698 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5699 
5700    Level: beginner
5701 
5702 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5703 @*/
5704 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5705 {
5706   static PetscInt inassm = 0;
5707   PetscBool       flg    = PETSC_FALSE;
5708 
5709   PetscFunctionBegin;
5710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5711   PetscValidType(mat, 1);
5712 
5713   inassm++;
5714   MatAssemblyEnd_InUse++;
5715   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5716     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5717     PetscTryTypeMethod(mat, assemblyend, type);
5718     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5719   } else PetscTryTypeMethod(mat, assemblyend, type);
5720 
5721   /* Flush assembly is not a true assembly */
5722   if (type != MAT_FLUSH_ASSEMBLY) {
5723     if (mat->num_ass) {
5724       if (!mat->symmetry_eternal) {
5725         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5726         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5727       }
5728       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5729       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5730     }
5731     mat->num_ass++;
5732     mat->assembled        = PETSC_TRUE;
5733     mat->ass_nonzerostate = mat->nonzerostate;
5734   }
5735 
5736   mat->insertmode = NOT_SET_VALUES;
5737   MatAssemblyEnd_InUse--;
5738   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5739   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5740     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5741 
5742     if (mat->checksymmetryonassembly) {
5743       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5744       if (flg) {
5745         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5746       } else {
5747         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5748       }
5749     }
5750     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5751   }
5752   inassm--;
5753   PetscFunctionReturn(PETSC_SUCCESS);
5754 }
5755 
5756 /*@
5757    MatSetOption - Sets a parameter option for a matrix. Some options
5758    may be specific to certain storage formats.  Some options
5759    determine how values will be inserted (or added). Sorted,
5760    row-oriented input will generally assemble the fastest. The default
5761    is row-oriented.
5762 
5763    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5764 
5765    Input Parameters:
5766 +  mat - the matrix
5767 .  option - the option, one of those listed below (and possibly others),
5768 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5769 
5770   Options Describing Matrix Structure:
5771 +    `MAT_SPD` - symmetric positive definite
5772 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5773 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5774 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5775 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5776 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5777 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5778 
5779    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5780    do not need to be computed (usually at a high cost)
5781 
5782    Options For Use with `MatSetValues()`:
5783    Insert a logically dense subblock, which can be
5784 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5785 
5786    These options reflect the data you pass in with `MatSetValues()`; it has
5787    nothing to do with how the data is stored internally in the matrix
5788    data structure.
5789 
5790    When (re)assembling a matrix, we can restrict the input for
5791    efficiency/debugging purposes.  These options include
5792 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5793 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5794 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5795 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5796 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5797 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5798         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5799         performance for very large process counts.
5800 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5801         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5802         functions, instead sending only neighbor messages.
5803 
5804    Level: intermediate
5805 
5806    Notes:
5807    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5808 
5809    Some options are relevant only for particular matrix types and
5810    are thus ignored by others.  Other options are not supported by
5811    certain matrix types and will generate an error message if set.
5812 
5813    If using Fortran to compute a matrix, one may need to
5814    use the column-oriented option (or convert to the row-oriented
5815    format).
5816 
5817    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5818    that would generate a new entry in the nonzero structure is instead
5819    ignored.  Thus, if memory has not already been allocated for this particular
5820    data, then the insertion is ignored. For dense matrices, in which
5821    the entire array is allocated, no entries are ever ignored.
5822    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5823 
5824    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5825    that would generate a new entry in the nonzero structure instead produces
5826    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
5827 
5828    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5829    that would generate a new entry that has not been preallocated will
5830    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5831    only.) This is a useful flag when debugging matrix memory preallocation.
5832    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5833 
5834    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5835    other processors should be dropped, rather than stashed.
5836    This is useful if you know that the "owning" processor is also
5837    always generating the correct matrix entries, so that PETSc need
5838    not transfer duplicate entries generated on another processor.
5839 
5840    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5841    searches during matrix assembly. When this flag is set, the hash table
5842    is created during the first matrix assembly. This hash table is
5843    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5844    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5845    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5846    supported by `MATMPIBAIJ` format only.
5847 
5848    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5849    are kept in the nonzero structure
5850 
5851    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5852    a zero location in the matrix
5853 
5854    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5855 
5856    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5857         zero row routines and thus improves performance for very large process counts.
5858 
5859    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5860         part of the matrix (since they should match the upper triangular part).
5861 
5862    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5863                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5864                      with finite difference schemes with non-periodic boundary conditions.
5865 
5866    Developer Note:
5867    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5868    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5869    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5870    not changed.
5871 
5872 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5873 @*/
5874 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5875 {
5876   PetscFunctionBegin;
5877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5878   if (op > 0) {
5879     PetscValidLogicalCollectiveEnum(mat, op, 2);
5880     PetscValidLogicalCollectiveBool(mat, flg, 3);
5881   }
5882 
5883   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);
5884 
5885   switch (op) {
5886   case MAT_FORCE_DIAGONAL_ENTRIES:
5887     mat->force_diagonals = flg;
5888     PetscFunctionReturn(PETSC_SUCCESS);
5889   case MAT_NO_OFF_PROC_ENTRIES:
5890     mat->nooffprocentries = flg;
5891     PetscFunctionReturn(PETSC_SUCCESS);
5892   case MAT_SUBSET_OFF_PROC_ENTRIES:
5893     mat->assembly_subset = flg;
5894     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5895 #if !defined(PETSC_HAVE_MPIUNI)
5896       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5897 #endif
5898       mat->stash.first_assembly_done = PETSC_FALSE;
5899     }
5900     PetscFunctionReturn(PETSC_SUCCESS);
5901   case MAT_NO_OFF_PROC_ZERO_ROWS:
5902     mat->nooffproczerorows = flg;
5903     PetscFunctionReturn(PETSC_SUCCESS);
5904   case MAT_SPD:
5905     if (flg) {
5906       mat->spd                    = PETSC_BOOL3_TRUE;
5907       mat->symmetric              = PETSC_BOOL3_TRUE;
5908       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5909     } else {
5910       mat->spd = PETSC_BOOL3_FALSE;
5911     }
5912     break;
5913   case MAT_SYMMETRIC:
5914     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5915     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5916 #if !defined(PETSC_USE_COMPLEX)
5917     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5918 #endif
5919     break;
5920   case MAT_HERMITIAN:
5921     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5922     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5923 #if !defined(PETSC_USE_COMPLEX)
5924     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5925 #endif
5926     break;
5927   case MAT_STRUCTURALLY_SYMMETRIC:
5928     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5929     break;
5930   case MAT_SYMMETRY_ETERNAL:
5931     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");
5932     mat->symmetry_eternal = flg;
5933     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5934     break;
5935   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5936     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");
5937     mat->structural_symmetry_eternal = flg;
5938     break;
5939   case MAT_SPD_ETERNAL:
5940     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");
5941     mat->spd_eternal = flg;
5942     if (flg) {
5943       mat->structural_symmetry_eternal = PETSC_TRUE;
5944       mat->symmetry_eternal            = PETSC_TRUE;
5945     }
5946     break;
5947   case MAT_STRUCTURE_ONLY:
5948     mat->structure_only = flg;
5949     break;
5950   case MAT_SORTED_FULL:
5951     mat->sortedfull = flg;
5952     break;
5953   default:
5954     break;
5955   }
5956   PetscTryTypeMethod(mat, setoption, op, flg);
5957   PetscFunctionReturn(PETSC_SUCCESS);
5958 }
5959 
5960 /*@
5961    MatGetOption - Gets a parameter option that has been set for a matrix.
5962 
5963    Logically Collective
5964 
5965    Input Parameters:
5966 +  mat - the matrix
5967 -  option - the option, this only responds to certain options, check the code for which ones
5968 
5969    Output Parameter:
5970 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5971 
5972    Level: intermediate
5973 
5974     Notes:
5975     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5976 
5977     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5978     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5979 
5980 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5981     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5982 @*/
5983 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5984 {
5985   PetscFunctionBegin;
5986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5987   PetscValidType(mat, 1);
5988 
5989   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);
5990   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()");
5991 
5992   switch (op) {
5993   case MAT_NO_OFF_PROC_ENTRIES:
5994     *flg = mat->nooffprocentries;
5995     break;
5996   case MAT_NO_OFF_PROC_ZERO_ROWS:
5997     *flg = mat->nooffproczerorows;
5998     break;
5999   case MAT_SYMMETRIC:
6000     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6001     break;
6002   case MAT_HERMITIAN:
6003     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6004     break;
6005   case MAT_STRUCTURALLY_SYMMETRIC:
6006     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6007     break;
6008   case MAT_SPD:
6009     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6010     break;
6011   case MAT_SYMMETRY_ETERNAL:
6012     *flg = mat->symmetry_eternal;
6013     break;
6014   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6015     *flg = mat->symmetry_eternal;
6016     break;
6017   default:
6018     break;
6019   }
6020   PetscFunctionReturn(PETSC_SUCCESS);
6021 }
6022 
6023 /*@
6024    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6025    this routine retains the old nonzero structure.
6026 
6027    Logically Collective
6028 
6029    Input Parameter:
6030 .  mat - the matrix
6031 
6032    Level: intermediate
6033 
6034    Note:
6035     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.
6036    See the Performance chapter of the users manual for information on preallocating matrices.
6037 
6038 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6039 @*/
6040 PetscErrorCode MatZeroEntries(Mat mat)
6041 {
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6044   PetscValidType(mat, 1);
6045   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6046   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");
6047   MatCheckPreallocated(mat, 1);
6048 
6049   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6050   PetscUseTypeMethod(mat, zeroentries);
6051   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6052   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6053   PetscFunctionReturn(PETSC_SUCCESS);
6054 }
6055 
6056 /*@
6057    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6058    of a set of rows and columns of a matrix.
6059 
6060    Collective
6061 
6062    Input Parameters:
6063 +  mat - the matrix
6064 .  numRows - the number of rows/columns to zero
6065 .  rows - the global row indices
6066 .  diag - value put in the diagonal of the eliminated rows
6067 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6068 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6069 
6070    Level: intermediate
6071 
6072    Notes:
6073    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6074 
6075    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6076    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
6077 
6078    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6079    Krylov method to take advantage of the known solution on the zeroed rows.
6080 
6081    For the parallel case, all processes that share the matrix (i.e.,
6082    those in the communicator used for matrix creation) MUST call this
6083    routine, regardless of whether any rows being zeroed are owned by
6084    them.
6085 
6086    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6087 
6088    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6089    list only rows local to itself).
6090 
6091    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6092 
6093 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6094           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6095 @*/
6096 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6097 {
6098   PetscFunctionBegin;
6099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6100   PetscValidType(mat, 1);
6101   if (numRows) PetscValidIntPointer(rows, 3);
6102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6103   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6104   MatCheckPreallocated(mat, 1);
6105 
6106   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6107   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6108   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6109   PetscFunctionReturn(PETSC_SUCCESS);
6110 }
6111 
6112 /*@
6113    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6114    of a set of rows and columns of a matrix.
6115 
6116    Collective
6117 
6118    Input Parameters:
6119 +  mat - the matrix
6120 .  is - the rows to zero
6121 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6122 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6123 -  b - optional vector of right hand side, that will be adjusted by provided solution
6124 
6125    Level: intermediate
6126 
6127    Note:
6128    See `MatZeroRowsColumns()` for details on how this routine operates.
6129 
6130 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6131           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6132 @*/
6133 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6134 {
6135   PetscInt        numRows;
6136   const PetscInt *rows;
6137 
6138   PetscFunctionBegin;
6139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6140   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6141   PetscValidType(mat, 1);
6142   PetscValidType(is, 2);
6143   PetscCall(ISGetLocalSize(is, &numRows));
6144   PetscCall(ISGetIndices(is, &rows));
6145   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6146   PetscCall(ISRestoreIndices(is, &rows));
6147   PetscFunctionReturn(PETSC_SUCCESS);
6148 }
6149 
6150 /*@
6151    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6152    of a set of rows of a matrix.
6153 
6154    Collective
6155 
6156    Input Parameters:
6157 +  mat - the matrix
6158 .  numRows - the number of rows to zero
6159 .  rows - the global row indices
6160 .  diag - value put in the diagonal of the zeroed rows
6161 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6162 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6163 
6164    Level: intermediate
6165 
6166    Notes:
6167    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6168 
6169    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6170 
6171    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6172    Krylov method to take advantage of the known solution on the zeroed rows.
6173 
6174    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)
6175    from the matrix.
6176 
6177    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6178    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
6179    formats this does not alter the nonzero structure.
6180 
6181    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6182    of the matrix is not changed the values are
6183    merely zeroed.
6184 
6185    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6186    formats can optionally remove the main diagonal entry from the
6187    nonzero structure as well, by passing 0.0 as the final argument).
6188 
6189    For the parallel case, all processes that share the matrix (i.e.,
6190    those in the communicator used for matrix creation) MUST call this
6191    routine, regardless of whether any rows being zeroed are owned by
6192    them.
6193 
6194    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6195    list only rows local to itself).
6196 
6197    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6198    owns that are to be zeroed. This saves a global synchronization in the implementation.
6199 
6200 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6201           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6202 @*/
6203 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6204 {
6205   PetscFunctionBegin;
6206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6207   PetscValidType(mat, 1);
6208   if (numRows) PetscValidIntPointer(rows, 3);
6209   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6210   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6211   MatCheckPreallocated(mat, 1);
6212 
6213   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6214   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6215   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6216   PetscFunctionReturn(PETSC_SUCCESS);
6217 }
6218 
6219 /*@
6220    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6221    of a set of rows of a matrix.
6222 
6223    Collective
6224 
6225    Input Parameters:
6226 +  mat - the matrix
6227 .  is - index set of rows to remove (if `NULL` then no row is removed)
6228 .  diag - value put in all diagonals of eliminated rows
6229 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6230 -  b - optional vector of right hand side, that will be adjusted by provided solution
6231 
6232    Level: intermediate
6233 
6234    Note:
6235    See `MatZeroRows()` for details on how this routine operates.
6236 
6237 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6238           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6239 @*/
6240 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6241 {
6242   PetscInt        numRows = 0;
6243   const PetscInt *rows    = NULL;
6244 
6245   PetscFunctionBegin;
6246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6247   PetscValidType(mat, 1);
6248   if (is) {
6249     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6250     PetscCall(ISGetLocalSize(is, &numRows));
6251     PetscCall(ISGetIndices(is, &rows));
6252   }
6253   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6254   if (is) PetscCall(ISRestoreIndices(is, &rows));
6255   PetscFunctionReturn(PETSC_SUCCESS);
6256 }
6257 
6258 /*@
6259    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6260    of a set of rows of a matrix. These rows must be local to the process.
6261 
6262    Collective
6263 
6264    Input Parameters:
6265 +  mat - the matrix
6266 .  numRows - the number of rows to remove
6267 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6268 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6269 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6270 -  b - optional vector of right hand side, that will be adjusted by provided solution
6271 
6272    Level: intermediate
6273 
6274    Notes:
6275    See `MatZeroRows()` for details on how this routine operates.
6276 
6277    The grid coordinates are across the entire grid, not just the local portion
6278 
6279    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6280    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6281    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6282    `DM_BOUNDARY_PERIODIC` boundary type.
6283 
6284    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
6285    a single value per point) you can skip filling those indices.
6286 
6287    Fortran Note:
6288    `idxm` and `idxn` should be declared as
6289 $     MatStencil idxm(4,m)
6290    and the values inserted using
6291 .vb
6292     idxm(MatStencil_i,1) = i
6293     idxm(MatStencil_j,1) = j
6294     idxm(MatStencil_k,1) = k
6295     idxm(MatStencil_c,1) = c
6296    etc
6297 .ve
6298 
6299 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6300           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6301 @*/
6302 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6303 {
6304   PetscInt  dim    = mat->stencil.dim;
6305   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6306   PetscInt *dims   = mat->stencil.dims + 1;
6307   PetscInt *starts = mat->stencil.starts;
6308   PetscInt *dxm    = (PetscInt *)rows;
6309   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6310 
6311   PetscFunctionBegin;
6312   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6313   PetscValidType(mat, 1);
6314   if (numRows) PetscValidPointer(rows, 3);
6315 
6316   PetscCall(PetscMalloc1(numRows, &jdxm));
6317   for (i = 0; i < numRows; ++i) {
6318     /* Skip unused dimensions (they are ordered k, j, i, c) */
6319     for (j = 0; j < 3 - sdim; ++j) dxm++;
6320     /* Local index in X dir */
6321     tmp = *dxm++ - starts[0];
6322     /* Loop over remaining dimensions */
6323     for (j = 0; j < dim - 1; ++j) {
6324       /* If nonlocal, set index to be negative */
6325       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6326       /* Update local index */
6327       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6328     }
6329     /* Skip component slot if necessary */
6330     if (mat->stencil.noc) dxm++;
6331     /* Local row number */
6332     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6333   }
6334   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6335   PetscCall(PetscFree(jdxm));
6336   PetscFunctionReturn(PETSC_SUCCESS);
6337 }
6338 
6339 /*@
6340    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6341    of a set of rows and columns of a matrix.
6342 
6343    Collective
6344 
6345    Input Parameters:
6346 +  mat - the matrix
6347 .  numRows - the number of rows/columns to remove
6348 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6349 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6350 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6351 -  b - optional vector of right hand side, that will be adjusted by provided solution
6352 
6353    Level: intermediate
6354 
6355    Notes:
6356    See `MatZeroRowsColumns()` for details on how this routine operates.
6357 
6358    The grid coordinates are across the entire grid, not just the local portion
6359 
6360    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6361    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6362    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6363    `DM_BOUNDARY_PERIODIC` boundary type.
6364 
6365    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
6366    a single value per point) you can skip filling those indices.
6367 
6368    Fortran Note:
6369    `idxm` and `idxn` should be declared as
6370 $     MatStencil idxm(4,m)
6371    and the values inserted using
6372 .vb
6373     idxm(MatStencil_i,1) = i
6374     idxm(MatStencil_j,1) = j
6375     idxm(MatStencil_k,1) = k
6376     idxm(MatStencil_c,1) = c
6377     etc
6378 .ve
6379 
6380 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6381           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6382 @*/
6383 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6384 {
6385   PetscInt  dim    = mat->stencil.dim;
6386   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6387   PetscInt *dims   = mat->stencil.dims + 1;
6388   PetscInt *starts = mat->stencil.starts;
6389   PetscInt *dxm    = (PetscInt *)rows;
6390   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6391 
6392   PetscFunctionBegin;
6393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6394   PetscValidType(mat, 1);
6395   if (numRows) PetscValidPointer(rows, 3);
6396 
6397   PetscCall(PetscMalloc1(numRows, &jdxm));
6398   for (i = 0; i < numRows; ++i) {
6399     /* Skip unused dimensions (they are ordered k, j, i, c) */
6400     for (j = 0; j < 3 - sdim; ++j) dxm++;
6401     /* Local index in X dir */
6402     tmp = *dxm++ - starts[0];
6403     /* Loop over remaining dimensions */
6404     for (j = 0; j < dim - 1; ++j) {
6405       /* If nonlocal, set index to be negative */
6406       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6407       /* Update local index */
6408       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6409     }
6410     /* Skip component slot if necessary */
6411     if (mat->stencil.noc) dxm++;
6412     /* Local row number */
6413     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6414   }
6415   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6416   PetscCall(PetscFree(jdxm));
6417   PetscFunctionReturn(PETSC_SUCCESS);
6418 }
6419 
6420 /*@C
6421    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6422    of a set of rows of a matrix; using local numbering of rows.
6423 
6424    Collective
6425 
6426    Input Parameters:
6427 +  mat - the matrix
6428 .  numRows - the number of rows to remove
6429 .  rows - the local row indices
6430 .  diag - value put in all diagonals of eliminated rows
6431 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6432 -  b - optional vector of right hand side, that will be adjusted by provided solution
6433 
6434    Level: intermediate
6435 
6436    Notes:
6437    Before calling `MatZeroRowsLocal()`, the user must first set the
6438    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6439 
6440    See `MatZeroRows()` for details on how this routine operates.
6441 
6442 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6443           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6444 @*/
6445 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6446 {
6447   PetscFunctionBegin;
6448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6449   PetscValidType(mat, 1);
6450   if (numRows) PetscValidIntPointer(rows, 3);
6451   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6452   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6453   MatCheckPreallocated(mat, 1);
6454 
6455   if (mat->ops->zerorowslocal) {
6456     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6457   } else {
6458     IS              is, newis;
6459     const PetscInt *newRows;
6460 
6461     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6462     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6463     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6464     PetscCall(ISGetIndices(newis, &newRows));
6465     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6466     PetscCall(ISRestoreIndices(newis, &newRows));
6467     PetscCall(ISDestroy(&newis));
6468     PetscCall(ISDestroy(&is));
6469   }
6470   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6471   PetscFunctionReturn(PETSC_SUCCESS);
6472 }
6473 
6474 /*@
6475    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6476    of a set of rows of a matrix; using local numbering of rows.
6477 
6478    Collective
6479 
6480    Input Parameters:
6481 +  mat - the matrix
6482 .  is - index set of rows to remove
6483 .  diag - value put in all diagonals of eliminated rows
6484 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6485 -  b - optional vector of right hand side, that will be adjusted by provided solution
6486 
6487    Level: intermediate
6488 
6489    Notes:
6490    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6491    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6492 
6493    See `MatZeroRows()` for details on how this routine operates.
6494 
6495 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6496           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6497 @*/
6498 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6499 {
6500   PetscInt        numRows;
6501   const PetscInt *rows;
6502 
6503   PetscFunctionBegin;
6504   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6505   PetscValidType(mat, 1);
6506   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6509   MatCheckPreallocated(mat, 1);
6510 
6511   PetscCall(ISGetLocalSize(is, &numRows));
6512   PetscCall(ISGetIndices(is, &rows));
6513   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6514   PetscCall(ISRestoreIndices(is, &rows));
6515   PetscFunctionReturn(PETSC_SUCCESS);
6516 }
6517 
6518 /*@
6519    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6520    of a set of rows and columns of a matrix; using local numbering of rows.
6521 
6522    Collective
6523 
6524    Input Parameters:
6525 +  mat - the matrix
6526 .  numRows - the number of rows to remove
6527 .  rows - the global row indices
6528 .  diag - value put in all diagonals of eliminated rows
6529 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6530 -  b - optional vector of right hand side, that will be adjusted by provided solution
6531 
6532    Level: intermediate
6533 
6534    Notes:
6535    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6536    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6537 
6538    See `MatZeroRowsColumns()` for details on how this routine operates.
6539 
6540 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6541           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6542 @*/
6543 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6544 {
6545   IS              is, newis;
6546   const PetscInt *newRows;
6547 
6548   PetscFunctionBegin;
6549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6550   PetscValidType(mat, 1);
6551   if (numRows) PetscValidIntPointer(rows, 3);
6552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6554   MatCheckPreallocated(mat, 1);
6555 
6556   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6557   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6558   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6559   PetscCall(ISGetIndices(newis, &newRows));
6560   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6561   PetscCall(ISRestoreIndices(newis, &newRows));
6562   PetscCall(ISDestroy(&newis));
6563   PetscCall(ISDestroy(&is));
6564   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6565   PetscFunctionReturn(PETSC_SUCCESS);
6566 }
6567 
6568 /*@
6569    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6570    of a set of rows and columns of a matrix; using local numbering of rows.
6571 
6572    Collective
6573 
6574    Input Parameters:
6575 +  mat - the matrix
6576 .  is - index set of rows to remove
6577 .  diag - value put in all diagonals of eliminated rows
6578 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6579 -  b - optional vector of right hand side, that will be adjusted by provided solution
6580 
6581    Level: intermediate
6582 
6583    Notes:
6584    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6585    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6586 
6587    See `MatZeroRowsColumns()` for details on how this routine operates.
6588 
6589 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6590           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6591 @*/
6592 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6593 {
6594   PetscInt        numRows;
6595   const PetscInt *rows;
6596 
6597   PetscFunctionBegin;
6598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6599   PetscValidType(mat, 1);
6600   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6601   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6602   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6603   MatCheckPreallocated(mat, 1);
6604 
6605   PetscCall(ISGetLocalSize(is, &numRows));
6606   PetscCall(ISGetIndices(is, &rows));
6607   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6608   PetscCall(ISRestoreIndices(is, &rows));
6609   PetscFunctionReturn(PETSC_SUCCESS);
6610 }
6611 
6612 /*@C
6613    MatGetSize - Returns the numbers of rows and columns in a matrix.
6614 
6615    Not Collective
6616 
6617    Input Parameter:
6618 .  mat - the matrix
6619 
6620    Output Parameters:
6621 +  m - the number of global rows
6622 -  n - the number of global columns
6623 
6624    Level: beginner
6625 
6626    Note:
6627    Both output parameters can be `NULL` on input.
6628 
6629 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6630 @*/
6631 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6632 {
6633   PetscFunctionBegin;
6634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6635   if (m) *m = mat->rmap->N;
6636   if (n) *n = mat->cmap->N;
6637   PetscFunctionReturn(PETSC_SUCCESS);
6638 }
6639 
6640 /*@C
6641    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6642    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6643 
6644    Not Collective
6645 
6646    Input Parameter:
6647 .  mat - the matrix
6648 
6649    Output Parameters:
6650 +  m - the number of local rows, use `NULL` to not obtain this value
6651 -  n - the number of local columns, use `NULL` to not obtain this value
6652 
6653    Level: beginner
6654 
6655 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6656 @*/
6657 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6658 {
6659   PetscFunctionBegin;
6660   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6661   if (m) PetscValidIntPointer(m, 2);
6662   if (n) PetscValidIntPointer(n, 3);
6663   if (m) *m = mat->rmap->n;
6664   if (n) *n = mat->cmap->n;
6665   PetscFunctionReturn(PETSC_SUCCESS);
6666 }
6667 
6668 /*@C
6669    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6670    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6671 
6672    Not Collective, unless matrix has not been allocated, then collective
6673 
6674    Input Parameter:
6675 .  mat - the matrix
6676 
6677    Output Parameters:
6678 +  m - the global index of the first local column, use `NULL` to not obtain this value
6679 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6680 
6681    Level: developer
6682 
6683 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6684 @*/
6685 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6686 {
6687   PetscFunctionBegin;
6688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6689   PetscValidType(mat, 1);
6690   if (m) PetscValidIntPointer(m, 2);
6691   if (n) PetscValidIntPointer(n, 3);
6692   MatCheckPreallocated(mat, 1);
6693   if (m) *m = mat->cmap->rstart;
6694   if (n) *n = mat->cmap->rend;
6695   PetscFunctionReturn(PETSC_SUCCESS);
6696 }
6697 
6698 /*@C
6699    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6700    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
6701    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6702 
6703    Not Collective
6704 
6705    Input Parameter:
6706 .  mat - the matrix
6707 
6708    Output Parameters:
6709 +  m - the global index of the first local row, use `NULL` to not obtain this value
6710 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6711 
6712    Level: beginner
6713 
6714    Note:
6715   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6716   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6717   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6718 
6719 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6720           `PetscLayout`
6721 @*/
6722 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6723 {
6724   PetscFunctionBegin;
6725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6726   PetscValidType(mat, 1);
6727   if (m) PetscValidIntPointer(m, 2);
6728   if (n) PetscValidIntPointer(n, 3);
6729   MatCheckPreallocated(mat, 1);
6730   if (m) *m = mat->rmap->rstart;
6731   if (n) *n = mat->rmap->rend;
6732   PetscFunctionReturn(PETSC_SUCCESS);
6733 }
6734 
6735 /*@C
6736    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6737    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
6738    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6739 
6740    Not Collective, unless matrix has not been allocated
6741 
6742    Input Parameter:
6743 .  mat - the matrix
6744 
6745    Output Parameter:
6746 .  ranges - start of each processors portion plus one more than the total length at the end
6747 
6748    Level: beginner
6749 
6750 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6751 @*/
6752 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6753 {
6754   PetscFunctionBegin;
6755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6756   PetscValidType(mat, 1);
6757   MatCheckPreallocated(mat, 1);
6758   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6759   PetscFunctionReturn(PETSC_SUCCESS);
6760 }
6761 
6762 /*@C
6763    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6764    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6765 
6766    Not Collective, unless matrix has not been allocated
6767 
6768    Input Parameter:
6769 .  mat - the matrix
6770 
6771    Output Parameter:
6772 .  ranges - start of each processors portion plus one more then the total length at the end
6773 
6774    Level: beginner
6775 
6776 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6777 @*/
6778 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6779 {
6780   PetscFunctionBegin;
6781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6782   PetscValidType(mat, 1);
6783   MatCheckPreallocated(mat, 1);
6784   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6785   PetscFunctionReturn(PETSC_SUCCESS);
6786 }
6787 
6788 /*@C
6789    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6790    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6791    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6792 
6793    Not Collective
6794 
6795    Input Parameter:
6796 .  A - matrix
6797 
6798    Output Parameters:
6799 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6800 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6801 
6802    Level: intermediate
6803 
6804 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6805 @*/
6806 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6807 {
6808   PetscErrorCode (*f)(Mat, IS *, IS *);
6809 
6810   PetscFunctionBegin;
6811   MatCheckPreallocated(A, 1);
6812   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6813   if (f) {
6814     PetscCall((*f)(A, rows, cols));
6815   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6816     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6817     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6818   }
6819   PetscFunctionReturn(PETSC_SUCCESS);
6820 }
6821 
6822 /*@C
6823    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6824    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6825    to complete the factorization.
6826 
6827    Collective
6828 
6829    Input Parameters:
6830 +  fact - the factorized matrix obtained with `MatGetFactor()`
6831 .  mat - the matrix
6832 .  row - row permutation
6833 .  col - column permutation
6834 -  info - structure containing
6835 .vb
6836       levels - number of levels of fill.
6837       expected fill - as ratio of original fill.
6838       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6839                 missing diagonal entries)
6840 .ve
6841 
6842    Level: developer
6843 
6844    Notes:
6845    See [Matrix Factorization](sec_matfactor) for additional information.
6846 
6847    Most users should employ the `KSP` interface for linear solvers
6848    instead of working directly with matrix algebra routines such as this.
6849    See, e.g., `KSPCreate()`.
6850 
6851    Uses the definition of level of fill as in Y. Saad, 2003
6852 
6853    Developer Note:
6854    The Fortran interface is not autogenerated as the
6855    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6856 
6857    References:
6858 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6859 
6860 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6861           `MatGetOrdering()`, `MatFactorInfo`
6862 @*/
6863 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6864 {
6865   PetscFunctionBegin;
6866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6867   PetscValidType(mat, 2);
6868   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6869   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6870   PetscValidPointer(info, 5);
6871   PetscValidPointer(fact, 1);
6872   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6873   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6874   if (!fact->ops->ilufactorsymbolic) {
6875     MatSolverType stype;
6876     PetscCall(MatFactorGetSolverType(fact, &stype));
6877     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6878   }
6879   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6880   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6881   MatCheckPreallocated(mat, 2);
6882 
6883   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6884   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6885   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6886   PetscFunctionReturn(PETSC_SUCCESS);
6887 }
6888 
6889 /*@C
6890    MatICCFactorSymbolic - Performs symbolic incomplete
6891    Cholesky factorization for a symmetric matrix.  Use
6892    `MatCholeskyFactorNumeric()` to complete the factorization.
6893 
6894    Collective
6895 
6896    Input Parameters:
6897 +  fact - the factorized matrix obtained with `MatGetFactor()`
6898 .  mat - the matrix to be factored
6899 .  perm - row and column permutation
6900 -  info - structure containing
6901 .vb
6902       levels - number of levels of fill.
6903       expected fill - as ratio of original fill.
6904 .ve
6905 
6906    Level: developer
6907 
6908    Notes:
6909    Most users should employ the `KSP` interface for linear solvers
6910    instead of working directly with matrix algebra routines such as this.
6911    See, e.g., `KSPCreate()`.
6912 
6913    This uses the definition of level of fill as in Y. Saad, 2003
6914 
6915    Developer Note:
6916    The Fortran interface is not autogenerated as the
6917    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6918 
6919    References:
6920 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6921 
6922 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6923 @*/
6924 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6925 {
6926   PetscFunctionBegin;
6927   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6928   PetscValidType(mat, 2);
6929   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6930   PetscValidPointer(info, 4);
6931   PetscValidPointer(fact, 1);
6932   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6933   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6934   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6935   if (!(fact)->ops->iccfactorsymbolic) {
6936     MatSolverType stype;
6937     PetscCall(MatFactorGetSolverType(fact, &stype));
6938     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6939   }
6940   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6941   MatCheckPreallocated(mat, 2);
6942 
6943   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6944   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6945   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6946   PetscFunctionReturn(PETSC_SUCCESS);
6947 }
6948 
6949 /*@C
6950    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6951    points to an array of valid matrices, they may be reused to store the new
6952    submatrices.
6953 
6954    Collective
6955 
6956    Input Parameters:
6957 +  mat - the matrix
6958 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6959 .  irow - index set of rows to extract
6960 .  icol - index set of columns to extract
6961 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6962 
6963    Output Parameter:
6964 .  submat - the array of submatrices
6965 
6966    Level: advanced
6967 
6968    Notes:
6969    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6970    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6971    to extract a parallel submatrix.
6972 
6973    Some matrix types place restrictions on the row and column
6974    indices, such as that they be sorted or that they be equal to each other.
6975 
6976    The index sets may not have duplicate entries.
6977 
6978    When extracting submatrices from a parallel matrix, each processor can
6979    form a different submatrix by setting the rows and columns of its
6980    individual index sets according to the local submatrix desired.
6981 
6982    When finished using the submatrices, the user should destroy
6983    them with `MatDestroySubMatrices()`.
6984 
6985    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6986    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6987 
6988    This routine creates the matrices in submat; you should NOT create them before
6989    calling it. It also allocates the array of matrix pointers submat.
6990 
6991    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6992    request one row/column in a block, they must request all rows/columns that are in
6993    that block. For example, if the block size is 2 you cannot request just row 0 and
6994    column 0.
6995 
6996    Fortran Note:
6997    The Fortran interface is slightly different from that given below; it
6998    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6999 
7000 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7001 @*/
7002 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7003 {
7004   PetscInt  i;
7005   PetscBool eq;
7006 
7007   PetscFunctionBegin;
7008   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7009   PetscValidType(mat, 1);
7010   if (n) {
7011     PetscValidPointer(irow, 3);
7012     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7013     PetscValidPointer(icol, 4);
7014     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7015   }
7016   PetscValidPointer(submat, 6);
7017   if (n && scall == MAT_REUSE_MATRIX) {
7018     PetscValidPointer(*submat, 6);
7019     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7020   }
7021   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7022   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7023   MatCheckPreallocated(mat, 1);
7024   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7025   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7026   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7027   for (i = 0; i < n; i++) {
7028     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7029     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7030     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7031 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7032     if (mat->boundtocpu && mat->bindingpropagates) {
7033       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7034       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7035     }
7036 #endif
7037   }
7038   PetscFunctionReturn(PETSC_SUCCESS);
7039 }
7040 
7041 /*@C
7042    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7043 
7044    Collective
7045 
7046    Input Parameters:
7047 +  mat - the matrix
7048 .  n   - the number of submatrixes to be extracted
7049 .  irow - index set of rows to extract
7050 .  icol - index set of columns to extract
7051 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7052 
7053    Output Parameter:
7054 .  submat - the array of submatrices
7055 
7056    Level: advanced
7057 
7058    Note:
7059    This is used by `PCGASM`
7060 
7061 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7062 @*/
7063 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7064 {
7065   PetscInt  i;
7066   PetscBool eq;
7067 
7068   PetscFunctionBegin;
7069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7070   PetscValidType(mat, 1);
7071   if (n) {
7072     PetscValidPointer(irow, 3);
7073     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7074     PetscValidPointer(icol, 4);
7075     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7076   }
7077   PetscValidPointer(submat, 6);
7078   if (n && scall == MAT_REUSE_MATRIX) {
7079     PetscValidPointer(*submat, 6);
7080     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7081   }
7082   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7083   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7084   MatCheckPreallocated(mat, 1);
7085 
7086   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7087   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7088   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7089   for (i = 0; i < n; i++) {
7090     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7091     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7092   }
7093   PetscFunctionReturn(PETSC_SUCCESS);
7094 }
7095 
7096 /*@C
7097    MatDestroyMatrices - Destroys an array of matrices.
7098 
7099    Collective
7100 
7101    Input Parameters:
7102 +  n - the number of local matrices
7103 -  mat - the matrices (this is a pointer to the array of matrices)
7104 
7105    Level: advanced
7106 
7107     Note:
7108     Frees not only the matrices, but also the array that contains the matrices
7109 
7110     Fortran Note:
7111     This does not free the array.
7112 
7113 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7114 @*/
7115 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7116 {
7117   PetscInt i;
7118 
7119   PetscFunctionBegin;
7120   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7121   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7122   PetscValidPointer(mat, 2);
7123 
7124   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7125 
7126   /* memory is allocated even if n = 0 */
7127   PetscCall(PetscFree(*mat));
7128   PetscFunctionReturn(PETSC_SUCCESS);
7129 }
7130 
7131 /*@C
7132    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7133 
7134    Collective
7135 
7136    Input Parameters:
7137 +  n - the number of local matrices
7138 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7139                        sequence of `MatCreateSubMatrices()`)
7140 
7141    Level: advanced
7142 
7143     Note:
7144     Frees not only the matrices, but also the array that contains the matrices
7145 
7146     Fortran Note:
7147     This does not free the array.
7148 
7149 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7150 @*/
7151 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7152 {
7153   Mat mat0;
7154 
7155   PetscFunctionBegin;
7156   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7157   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7158   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7159   PetscValidPointer(mat, 2);
7160 
7161   mat0 = (*mat)[0];
7162   if (mat0 && mat0->ops->destroysubmatrices) {
7163     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7164   } else {
7165     PetscCall(MatDestroyMatrices(n, mat));
7166   }
7167   PetscFunctionReturn(PETSC_SUCCESS);
7168 }
7169 
7170 /*@C
7171    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7172 
7173    Collective
7174 
7175    Input Parameter:
7176 .  mat - the matrix
7177 
7178    Output Parameter:
7179 .  matstruct - the sequential matrix with the nonzero structure of mat
7180 
7181   Level: developer
7182 
7183 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7184 @*/
7185 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7186 {
7187   PetscFunctionBegin;
7188   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7189   PetscValidPointer(matstruct, 2);
7190 
7191   PetscValidType(mat, 1);
7192   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7193   MatCheckPreallocated(mat, 1);
7194 
7195   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7196   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7197   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7198   PetscFunctionReturn(PETSC_SUCCESS);
7199 }
7200 
7201 /*@C
7202    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7203 
7204    Collective
7205 
7206    Input Parameter:
7207 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7208                        sequence of `MatGetSequentialNonzeroStructure()`)
7209 
7210    Level: advanced
7211 
7212     Note:
7213     Frees not only the matrices, but also the array that contains the matrices
7214 
7215 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7216 @*/
7217 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7218 {
7219   PetscFunctionBegin;
7220   PetscValidPointer(mat, 1);
7221   PetscCall(MatDestroy(mat));
7222   PetscFunctionReturn(PETSC_SUCCESS);
7223 }
7224 
7225 /*@
7226    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7227    replaces the index sets by larger ones that represent submatrices with
7228    additional overlap.
7229 
7230    Collective
7231 
7232    Input Parameters:
7233 +  mat - the matrix
7234 .  n   - the number of index sets
7235 .  is  - the array of index sets (these index sets will changed during the call)
7236 -  ov  - the additional overlap requested
7237 
7238    Options Database Key:
7239 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7240 
7241    Level: developer
7242 
7243    Note:
7244    The computed overlap preserves the matrix block sizes when the blocks are square.
7245    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7246    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7247 
7248 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7249 @*/
7250 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7251 {
7252   PetscInt i, bs, cbs;
7253 
7254   PetscFunctionBegin;
7255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7256   PetscValidType(mat, 1);
7257   PetscValidLogicalCollectiveInt(mat, n, 2);
7258   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7259   if (n) {
7260     PetscValidPointer(is, 3);
7261     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7262   }
7263   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7264   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7265   MatCheckPreallocated(mat, 1);
7266 
7267   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7268   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7269   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7270   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7271   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7272   if (bs == cbs) {
7273     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7274   }
7275   PetscFunctionReturn(PETSC_SUCCESS);
7276 }
7277 
7278 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7279 
7280 /*@
7281    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7282    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7283    additional overlap.
7284 
7285    Collective
7286 
7287    Input Parameters:
7288 +  mat - the matrix
7289 .  n   - the number of index sets
7290 .  is  - the array of index sets (these index sets will changed during the call)
7291 -  ov  - the additional overlap requested
7292 
7293 `   Options Database Key:
7294 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7295 
7296    Level: developer
7297 
7298 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7299 @*/
7300 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7301 {
7302   PetscInt i;
7303 
7304   PetscFunctionBegin;
7305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7306   PetscValidType(mat, 1);
7307   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7308   if (n) {
7309     PetscValidPointer(is, 3);
7310     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7311   }
7312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7314   MatCheckPreallocated(mat, 1);
7315   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7316   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7317   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7318   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7319   PetscFunctionReturn(PETSC_SUCCESS);
7320 }
7321 
7322 /*@
7323    MatGetBlockSize - Returns the matrix block size.
7324 
7325    Not Collective
7326 
7327    Input Parameter:
7328 .  mat - the matrix
7329 
7330    Output Parameter:
7331 .  bs - block size
7332 
7333    Level: intermediate
7334 
7335    Notes:
7336     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7337 
7338    If the block size has not been set yet this routine returns 1.
7339 
7340 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7341 @*/
7342 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7343 {
7344   PetscFunctionBegin;
7345   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7346   PetscValidIntPointer(bs, 2);
7347   *bs = PetscAbs(mat->rmap->bs);
7348   PetscFunctionReturn(PETSC_SUCCESS);
7349 }
7350 
7351 /*@
7352    MatGetBlockSizes - Returns the matrix block row and column sizes.
7353 
7354    Not Collective
7355 
7356    Input Parameter:
7357 .  mat - the matrix
7358 
7359    Output Parameters:
7360 +  rbs - row block size
7361 -  cbs - column block size
7362 
7363    Level: intermediate
7364 
7365    Notes:
7366     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7367     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7368 
7369    If a block size has not been set yet this routine returns 1.
7370 
7371 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7372 @*/
7373 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7374 {
7375   PetscFunctionBegin;
7376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7377   if (rbs) PetscValidIntPointer(rbs, 2);
7378   if (cbs) PetscValidIntPointer(cbs, 3);
7379   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7380   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7381   PetscFunctionReturn(PETSC_SUCCESS);
7382 }
7383 
7384 /*@
7385    MatSetBlockSize - Sets the matrix block size.
7386 
7387    Logically Collective
7388 
7389    Input Parameters:
7390 +  mat - the matrix
7391 -  bs - block size
7392 
7393    Level: intermediate
7394 
7395    Notes:
7396     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7397     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7398 
7399     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7400     is compatible with the matrix local sizes.
7401 
7402 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7403 @*/
7404 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7405 {
7406   PetscFunctionBegin;
7407   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7408   PetscValidLogicalCollectiveInt(mat, bs, 2);
7409   PetscCall(MatSetBlockSizes(mat, bs, bs));
7410   PetscFunctionReturn(PETSC_SUCCESS);
7411 }
7412 
7413 typedef struct {
7414   PetscInt         n;
7415   IS              *is;
7416   Mat             *mat;
7417   PetscObjectState nonzerostate;
7418   Mat              C;
7419 } EnvelopeData;
7420 
7421 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7422 {
7423   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7424   PetscCall(PetscFree(edata->is));
7425   PetscCall(PetscFree(edata));
7426   return PETSC_SUCCESS;
7427 }
7428 
7429 /*
7430    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7431          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7432 
7433    Collective
7434 
7435    Input Parameter:
7436 .  mat - the matrix
7437 
7438    Notes:
7439      There can be zeros within the blocks
7440 
7441      The blocks can overlap between processes, including laying on more than two processes
7442 
7443 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7444 */
7445 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7446 {
7447   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7448   PetscInt          *diag, *odiag, sc;
7449   VecScatter         scatter;
7450   PetscScalar       *seqv;
7451   const PetscScalar *parv;
7452   const PetscInt    *ia, *ja;
7453   PetscBool          set, flag, done;
7454   Mat                AA = mat, A;
7455   MPI_Comm           comm;
7456   PetscMPIInt        rank, size, tag;
7457   MPI_Status         status;
7458   PetscContainer     container;
7459   EnvelopeData      *edata;
7460   Vec                seq, par;
7461   IS                 isglobal;
7462 
7463   PetscFunctionBegin;
7464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7465   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7466   if (!set || !flag) {
7467     /* TOO: only needs nonzero structure of transpose */
7468     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7469     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7470   }
7471   PetscCall(MatAIJGetLocalMat(AA, &A));
7472   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7473   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7474 
7475   PetscCall(MatGetLocalSize(mat, &n, NULL));
7476   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7477   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7478   PetscCallMPI(MPI_Comm_size(comm, &size));
7479   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7480 
7481   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7482 
7483   if (rank > 0) {
7484     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7485     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7486   }
7487   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7488   for (i = 0; i < n; i++) {
7489     env = PetscMax(env, ja[ia[i + 1] - 1]);
7490     II  = rstart + i;
7491     if (env == II) {
7492       starts[lblocks]  = tbs;
7493       sizes[lblocks++] = 1 + II - tbs;
7494       tbs              = 1 + II;
7495     }
7496   }
7497   if (rank < size - 1) {
7498     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7499     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7500   }
7501 
7502   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7503   if (!set || !flag) PetscCall(MatDestroy(&AA));
7504   PetscCall(MatDestroy(&A));
7505 
7506   PetscCall(PetscNew(&edata));
7507   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7508   edata->n = lblocks;
7509   /* create IS needed for extracting blocks from the original matrix */
7510   PetscCall(PetscMalloc1(lblocks, &edata->is));
7511   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7512 
7513   /* Create the resulting inverse matrix structure with preallocation information */
7514   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7515   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7516   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7517   PetscCall(MatSetType(edata->C, MATAIJ));
7518 
7519   /* Communicate the start and end of each row, from each block to the correct rank */
7520   /* TODO: Use PetscSF instead of VecScatter */
7521   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7522   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7523   PetscCall(VecGetArrayWrite(seq, &seqv));
7524   for (PetscInt i = 0; i < lblocks; i++) {
7525     for (PetscInt j = 0; j < sizes[i]; j++) {
7526       seqv[cnt]     = starts[i];
7527       seqv[cnt + 1] = starts[i] + sizes[i];
7528       cnt += 2;
7529     }
7530   }
7531   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7532   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7533   sc -= cnt;
7534   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7535   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7536   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7537   PetscCall(ISDestroy(&isglobal));
7538   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7539   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7540   PetscCall(VecScatterDestroy(&scatter));
7541   PetscCall(VecDestroy(&seq));
7542   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7543   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7544   PetscCall(VecGetArrayRead(par, &parv));
7545   cnt = 0;
7546   PetscCall(MatGetSize(mat, NULL, &n));
7547   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7548     PetscInt start, end, d = 0, od = 0;
7549 
7550     start = (PetscInt)PetscRealPart(parv[cnt]);
7551     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7552     cnt += 2;
7553 
7554     if (start < cstart) {
7555       od += cstart - start + n - cend;
7556       d += cend - cstart;
7557     } else if (start < cend) {
7558       od += n - cend;
7559       d += cend - start;
7560     } else od += n - start;
7561     if (end <= cstart) {
7562       od -= cstart - end + n - cend;
7563       d -= cend - cstart;
7564     } else if (end < cend) {
7565       od -= n - cend;
7566       d -= cend - end;
7567     } else od -= n - end;
7568 
7569     odiag[i] = od;
7570     diag[i]  = d;
7571   }
7572   PetscCall(VecRestoreArrayRead(par, &parv));
7573   PetscCall(VecDestroy(&par));
7574   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7575   PetscCall(PetscFree2(diag, odiag));
7576   PetscCall(PetscFree2(sizes, starts));
7577 
7578   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7579   PetscCall(PetscContainerSetPointer(container, edata));
7580   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7581   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7582   PetscCall(PetscObjectDereference((PetscObject)container));
7583   PetscFunctionReturn(PETSC_SUCCESS);
7584 }
7585 
7586 /*@
7587   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7588 
7589   Collective
7590 
7591   Input Parameters:
7592 + A - the matrix
7593 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7594 
7595   Output Parameter:
7596 . C - matrix with inverted block diagonal of `A`
7597 
7598   Level: advanced
7599 
7600   Note:
7601      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7602 
7603 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7604 @*/
7605 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7606 {
7607   PetscContainer   container;
7608   EnvelopeData    *edata;
7609   PetscObjectState nonzerostate;
7610 
7611   PetscFunctionBegin;
7612   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7613   if (!container) {
7614     PetscCall(MatComputeVariableBlockEnvelope(A));
7615     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7616   }
7617   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7618   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7619   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7620   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7621 
7622   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7623   *C = edata->C;
7624 
7625   for (PetscInt i = 0; i < edata->n; i++) {
7626     Mat          D;
7627     PetscScalar *dvalues;
7628 
7629     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7630     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7631     PetscCall(MatSeqDenseInvert(D));
7632     PetscCall(MatDenseGetArray(D, &dvalues));
7633     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7634     PetscCall(MatDestroy(&D));
7635   }
7636   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7637   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7638   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7639   PetscFunctionReturn(PETSC_SUCCESS);
7640 }
7641 
7642 /*@
7643    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7644 
7645    Logically Collective
7646 
7647    Input Parameters:
7648 +  mat - the matrix
7649 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7650 -  bsizes - the block sizes
7651 
7652    Level: intermediate
7653 
7654    Notes:
7655     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7656 
7657     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.
7658 
7659 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7660           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7661 @*/
7662 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7663 {
7664   PetscInt i, ncnt = 0, nlocal;
7665 
7666   PetscFunctionBegin;
7667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7668   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7669   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7670   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7671   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);
7672   PetscCall(PetscFree(mat->bsizes));
7673   mat->nblocks = nblocks;
7674   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7675   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7676   PetscFunctionReturn(PETSC_SUCCESS);
7677 }
7678 
7679 /*@C
7680    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7681 
7682    Logically Collective; No Fortran Support
7683 
7684    Input Parameter:
7685 .  mat - the matrix
7686 
7687    Output Parameters:
7688 +  nblocks - the number of blocks on this process
7689 -  bsizes - the block sizes
7690 
7691    Level: intermediate
7692 
7693 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7694 @*/
7695 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7696 {
7697   PetscFunctionBegin;
7698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7699   *nblocks = mat->nblocks;
7700   *bsizes  = mat->bsizes;
7701   PetscFunctionReturn(PETSC_SUCCESS);
7702 }
7703 
7704 /*@
7705    MatSetBlockSizes - Sets the matrix block row and column sizes.
7706 
7707    Logically Collective
7708 
7709    Input Parameters:
7710 +  mat - the matrix
7711 .  rbs - row block size
7712 -  cbs - column block size
7713 
7714    Level: intermediate
7715 
7716    Notes:
7717     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7718     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7719     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7720 
7721     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7722     are compatible with the matrix local sizes.
7723 
7724     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7725 
7726 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7727 @*/
7728 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7729 {
7730   PetscFunctionBegin;
7731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7732   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7733   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7734   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7735   if (mat->rmap->refcnt) {
7736     ISLocalToGlobalMapping l2g  = NULL;
7737     PetscLayout            nmap = NULL;
7738 
7739     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7740     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7741     PetscCall(PetscLayoutDestroy(&mat->rmap));
7742     mat->rmap          = nmap;
7743     mat->rmap->mapping = l2g;
7744   }
7745   if (mat->cmap->refcnt) {
7746     ISLocalToGlobalMapping l2g  = NULL;
7747     PetscLayout            nmap = NULL;
7748 
7749     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7750     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7751     PetscCall(PetscLayoutDestroy(&mat->cmap));
7752     mat->cmap          = nmap;
7753     mat->cmap->mapping = l2g;
7754   }
7755   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7756   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7757   PetscFunctionReturn(PETSC_SUCCESS);
7758 }
7759 
7760 /*@
7761    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7762 
7763    Logically Collective
7764 
7765    Input Parameters:
7766 +  mat - the matrix
7767 .  fromRow - matrix from which to copy row block size
7768 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7769 
7770    Level: developer
7771 
7772 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7773 @*/
7774 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7775 {
7776   PetscFunctionBegin;
7777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7778   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7779   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7780   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7781   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7782   PetscFunctionReturn(PETSC_SUCCESS);
7783 }
7784 
7785 /*@
7786    MatResidual - Default routine to calculate the residual r = b - Ax
7787 
7788    Collective
7789 
7790    Input Parameters:
7791 +  mat - the matrix
7792 .  b   - the right-hand-side
7793 -  x   - the approximate solution
7794 
7795    Output Parameter:
7796 .  r - location to store the residual
7797 
7798    Level: developer
7799 
7800 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7801 @*/
7802 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7803 {
7804   PetscFunctionBegin;
7805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7806   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7807   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7808   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7809   PetscValidType(mat, 1);
7810   MatCheckPreallocated(mat, 1);
7811   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7812   if (!mat->ops->residual) {
7813     PetscCall(MatMult(mat, x, r));
7814     PetscCall(VecAYPX(r, -1.0, b));
7815   } else {
7816     PetscUseTypeMethod(mat, residual, b, x, r);
7817   }
7818   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7819   PetscFunctionReturn(PETSC_SUCCESS);
7820 }
7821 
7822 /*MC
7823     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7824 
7825     Synopsis:
7826     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7827 
7828     Not Collective
7829 
7830     Input Parameters:
7831 +   A - the matrix
7832 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7833 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7834 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7835                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7836                  always used.
7837 
7838     Output Parameters:
7839 +   n - number of local rows in the (possibly compressed) matrix
7840 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7841 .   ja - the column indices
7842 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7843            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7844 
7845     Level: developer
7846 
7847     Note:
7848     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7849 
7850 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7851 M*/
7852 
7853 /*MC
7854     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7855 
7856     Synopsis:
7857     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7858 
7859     Not Collective
7860 
7861     Input Parameters:
7862 +   A - the  matrix
7863 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7864 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7865     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7866                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7867                  always used.
7868 .   n - number of local rows in the (possibly compressed) matrix
7869 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7870 .   ja - the column indices
7871 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7872            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7873 
7874     Level: developer
7875 
7876 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7877 M*/
7878 
7879 /*@C
7880     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7881 
7882    Collective
7883 
7884     Input Parameters:
7885 +   mat - the matrix
7886 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7887 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7888 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7889                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7890                  always used.
7891 
7892     Output Parameters:
7893 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7894 .   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
7895 .   ja - the column indices, use `NULL` if not needed
7896 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7897            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7898 
7899     Level: developer
7900 
7901     Notes:
7902     You CANNOT change any of the ia[] or ja[] values.
7903 
7904     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7905 
7906     Fortran Notes:
7907     Use
7908 .vb
7909     PetscInt, pointer :: ia(:),ja(:)
7910     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7911     ! Access the ith and jth entries via ia(i) and ja(j)
7912 .ve
7913    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7914 
7915 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7916 @*/
7917 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7918 {
7919   PetscFunctionBegin;
7920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7921   PetscValidType(mat, 1);
7922   if (n) PetscValidIntPointer(n, 5);
7923   if (ia) PetscValidPointer(ia, 6);
7924   if (ja) PetscValidPointer(ja, 7);
7925   if (done) PetscValidBoolPointer(done, 8);
7926   MatCheckPreallocated(mat, 1);
7927   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7928   else {
7929     if (done) *done = PETSC_TRUE;
7930     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7931     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7932     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7933   }
7934   PetscFunctionReturn(PETSC_SUCCESS);
7935 }
7936 
7937 /*@C
7938     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7939 
7940     Collective
7941 
7942     Input Parameters:
7943 +   mat - the matrix
7944 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7945 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7946                 symmetrized
7947 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7948                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7949                  always used.
7950 .   n - number of columns in the (possibly compressed) matrix
7951 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7952 -   ja - the row indices
7953 
7954     Output Parameter:
7955 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7956 
7957     Level: developer
7958 
7959 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7960 @*/
7961 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7962 {
7963   PetscFunctionBegin;
7964   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7965   PetscValidType(mat, 1);
7966   PetscValidIntPointer(n, 5);
7967   if (ia) PetscValidPointer(ia, 6);
7968   if (ja) PetscValidPointer(ja, 7);
7969   PetscValidBoolPointer(done, 8);
7970   MatCheckPreallocated(mat, 1);
7971   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7972   else {
7973     *done = PETSC_TRUE;
7974     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7975   }
7976   PetscFunctionReturn(PETSC_SUCCESS);
7977 }
7978 
7979 /*@C
7980     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7981 
7982     Collective
7983 
7984     Input Parameters:
7985 +   mat - the matrix
7986 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7987 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7988 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7989                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7990                  always used.
7991 .   n - size of (possibly compressed) matrix
7992 .   ia - the row pointers
7993 -   ja - the column indices
7994 
7995     Output Parameter:
7996 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7997 
7998     Level: developer
7999 
8000     Note:
8001     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8002     us of the array after it has been restored. If you pass `NULL`, it will
8003     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8004 
8005     Fortran Note:
8006    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8007 
8008 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8009 @*/
8010 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8011 {
8012   PetscFunctionBegin;
8013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8014   PetscValidType(mat, 1);
8015   if (ia) PetscValidPointer(ia, 6);
8016   if (ja) PetscValidPointer(ja, 7);
8017   if (done) PetscValidBoolPointer(done, 8);
8018   MatCheckPreallocated(mat, 1);
8019 
8020   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8021   else {
8022     if (done) *done = PETSC_TRUE;
8023     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8024     if (n) *n = 0;
8025     if (ia) *ia = NULL;
8026     if (ja) *ja = NULL;
8027   }
8028   PetscFunctionReturn(PETSC_SUCCESS);
8029 }
8030 
8031 /*@C
8032     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8033 
8034     Collective
8035 
8036     Input Parameters:
8037 +   mat - the matrix
8038 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8039 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8040 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8041                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8042                  always used.
8043 
8044     Output Parameters:
8045 +   n - size of (possibly compressed) matrix
8046 .   ia - the column pointers
8047 .   ja - the row indices
8048 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8049 
8050     Level: developer
8051 
8052 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8053 @*/
8054 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8055 {
8056   PetscFunctionBegin;
8057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8058   PetscValidType(mat, 1);
8059   if (ia) PetscValidPointer(ia, 6);
8060   if (ja) PetscValidPointer(ja, 7);
8061   PetscValidBoolPointer(done, 8);
8062   MatCheckPreallocated(mat, 1);
8063 
8064   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8065   else {
8066     *done = PETSC_TRUE;
8067     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8068     if (n) *n = 0;
8069     if (ia) *ia = NULL;
8070     if (ja) *ja = NULL;
8071   }
8072   PetscFunctionReturn(PETSC_SUCCESS);
8073 }
8074 
8075 /*@C
8076     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8077 
8078     Collective
8079 
8080     Input Parameters:
8081 +   mat - the matrix
8082 .   ncolors - maximum color value
8083 .   n   - number of entries in colorarray
8084 -   colorarray - array indicating color for each column
8085 
8086     Output Parameter:
8087 .   iscoloring - coloring generated using colorarray information
8088 
8089     Level: developer
8090 
8091 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8092 @*/
8093 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8094 {
8095   PetscFunctionBegin;
8096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8097   PetscValidType(mat, 1);
8098   PetscValidIntPointer(colorarray, 4);
8099   PetscValidPointer(iscoloring, 5);
8100   MatCheckPreallocated(mat, 1);
8101 
8102   if (!mat->ops->coloringpatch) {
8103     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8104   } else {
8105     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8106   }
8107   PetscFunctionReturn(PETSC_SUCCESS);
8108 }
8109 
8110 /*@
8111    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8112 
8113    Logically Collective
8114 
8115    Input Parameter:
8116 .  mat - the factored matrix to be reset
8117 
8118    Level: developer
8119 
8120    Notes:
8121    This routine should be used only with factored matrices formed by in-place
8122    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8123    format).  This option can save memory, for example, when solving nonlinear
8124    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8125    ILU(0) preconditioner.
8126 
8127    One can specify in-place ILU(0) factorization by calling
8128 .vb
8129      PCType(pc,PCILU);
8130      PCFactorSeUseInPlace(pc);
8131 .ve
8132    or by using the options -pc_type ilu -pc_factor_in_place
8133 
8134    In-place factorization ILU(0) can also be used as a local
8135    solver for the blocks within the block Jacobi or additive Schwarz
8136    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8137    for details on setting local solver options.
8138 
8139    Most users should employ the `KSP` interface for linear solvers
8140    instead of working directly with matrix algebra routines such as this.
8141    See, e.g., `KSPCreate()`.
8142 
8143 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8144 @*/
8145 PetscErrorCode MatSetUnfactored(Mat mat)
8146 {
8147   PetscFunctionBegin;
8148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8149   PetscValidType(mat, 1);
8150   MatCheckPreallocated(mat, 1);
8151   mat->factortype = MAT_FACTOR_NONE;
8152   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8153   PetscUseTypeMethod(mat, setunfactored);
8154   PetscFunctionReturn(PETSC_SUCCESS);
8155 }
8156 
8157 /*MC
8158     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8159 
8160     Synopsis:
8161     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8162 
8163     Not Collective
8164 
8165     Input Parameter:
8166 .   x - matrix
8167 
8168     Output Parameters:
8169 +   xx_v - the Fortran pointer to the array
8170 -   ierr - error code
8171 
8172     Example of Usage:
8173 .vb
8174       PetscScalar, pointer xx_v(:,:)
8175       ....
8176       call MatDenseGetArrayF90(x,xx_v,ierr)
8177       a = xx_v(3)
8178       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8179 .ve
8180 
8181     Level: advanced
8182 
8183 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8184 M*/
8185 
8186 /*MC
8187     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8188     accessed with `MatDenseGetArrayF90()`.
8189 
8190     Synopsis:
8191     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8192 
8193     Not Collective
8194 
8195     Input Parameters:
8196 +   x - matrix
8197 -   xx_v - the Fortran90 pointer to the array
8198 
8199     Output Parameter:
8200 .   ierr - error code
8201 
8202     Example of Usage:
8203 .vb
8204        PetscScalar, pointer xx_v(:,:)
8205        ....
8206        call MatDenseGetArrayF90(x,xx_v,ierr)
8207        a = xx_v(3)
8208        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8209 .ve
8210 
8211     Level: advanced
8212 
8213 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8214 M*/
8215 
8216 /*MC
8217     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8218 
8219     Synopsis:
8220     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8221 
8222     Not Collective
8223 
8224     Input Parameter:
8225 .   x - matrix
8226 
8227     Output Parameters:
8228 +   xx_v - the Fortran pointer to the array
8229 -   ierr - error code
8230 
8231     Example of Usage:
8232 .vb
8233       PetscScalar, pointer xx_v(:)
8234       ....
8235       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8236       a = xx_v(3)
8237       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8238 .ve
8239 
8240     Level: advanced
8241 
8242 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8243 M*/
8244 
8245 /*MC
8246     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8247     accessed with `MatSeqAIJGetArrayF90()`.
8248 
8249     Synopsis:
8250     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8251 
8252     Not Collective
8253 
8254     Input Parameters:
8255 +   x - matrix
8256 -   xx_v - the Fortran90 pointer to the array
8257 
8258     Output Parameter:
8259 .   ierr - error code
8260 
8261     Example of Usage:
8262 .vb
8263        PetscScalar, pointer xx_v(:)
8264        ....
8265        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8266        a = xx_v(3)
8267        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8268 .ve
8269 
8270     Level: advanced
8271 
8272 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8273 M*/
8274 
8275 /*@
8276     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8277                       as the original matrix.
8278 
8279     Collective
8280 
8281     Input Parameters:
8282 +   mat - the original matrix
8283 .   isrow - parallel `IS` containing the rows this processor should obtain
8284 .   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.
8285 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8286 
8287     Output Parameter:
8288 .   newmat - the new submatrix, of the same type as the original matrix
8289 
8290     Level: advanced
8291 
8292     Notes:
8293     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8294 
8295     Some matrix types place restrictions on the row and column indices, such
8296     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;
8297     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8298 
8299     The index sets may not have duplicate entries.
8300 
8301       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8302    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8303    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8304    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8305    you are finished using it.
8306 
8307     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8308     the input matrix.
8309 
8310     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8311 
8312    Example usage:
8313    Consider the following 8x8 matrix with 34 non-zero values, that is
8314    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8315    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8316    as follows
8317 .vb
8318             1  2  0  |  0  3  0  |  0  4
8319     Proc0   0  5  6  |  7  0  0  |  8  0
8320             9  0 10  | 11  0  0  | 12  0
8321     -------------------------------------
8322            13  0 14  | 15 16 17  |  0  0
8323     Proc1   0 18  0  | 19 20 21  |  0  0
8324             0  0  0  | 22 23  0  | 24  0
8325     -------------------------------------
8326     Proc2  25 26 27  |  0  0 28  | 29  0
8327            30  0  0  | 31 32 33  |  0 34
8328 .ve
8329 
8330     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8331 
8332 .vb
8333             2  0  |  0  3  0  |  0
8334     Proc0   5  6  |  7  0  0  |  8
8335     -------------------------------
8336     Proc1  18  0  | 19 20 21  |  0
8337     -------------------------------
8338     Proc2  26 27  |  0  0 28  | 29
8339             0  0  | 31 32 33  |  0
8340 .ve
8341 
8342 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8343 @*/
8344 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8345 {
8346   PetscMPIInt size;
8347   Mat        *local;
8348   IS          iscoltmp;
8349   PetscBool   flg;
8350 
8351   PetscFunctionBegin;
8352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8353   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8354   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8355   PetscValidPointer(newmat, 5);
8356   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8357   PetscValidType(mat, 1);
8358   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8359   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8360 
8361   MatCheckPreallocated(mat, 1);
8362   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8363 
8364   if (!iscol || isrow == iscol) {
8365     PetscBool   stride;
8366     PetscMPIInt grabentirematrix = 0, grab;
8367     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8368     if (stride) {
8369       PetscInt first, step, n, rstart, rend;
8370       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8371       if (step == 1) {
8372         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8373         if (rstart == first) {
8374           PetscCall(ISGetLocalSize(isrow, &n));
8375           if (n == rend - rstart) grabentirematrix = 1;
8376         }
8377       }
8378     }
8379     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8380     if (grab) {
8381       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8382       if (cll == MAT_INITIAL_MATRIX) {
8383         *newmat = mat;
8384         PetscCall(PetscObjectReference((PetscObject)mat));
8385       }
8386       PetscFunctionReturn(PETSC_SUCCESS);
8387     }
8388   }
8389 
8390   if (!iscol) {
8391     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8392   } else {
8393     iscoltmp = iscol;
8394   }
8395 
8396   /* if original matrix is on just one processor then use submatrix generated */
8397   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8398     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8399     goto setproperties;
8400   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8401     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8402     *newmat = *local;
8403     PetscCall(PetscFree(local));
8404     goto setproperties;
8405   } else if (!mat->ops->createsubmatrix) {
8406     /* Create a new matrix type that implements the operation using the full matrix */
8407     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8408     switch (cll) {
8409     case MAT_INITIAL_MATRIX:
8410       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8411       break;
8412     case MAT_REUSE_MATRIX:
8413       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8414       break;
8415     default:
8416       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8417     }
8418     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8419     goto setproperties;
8420   }
8421 
8422   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8423   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8424   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8425 
8426 setproperties:
8427   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8428   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8429   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8430   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8431   PetscFunctionReturn(PETSC_SUCCESS);
8432 }
8433 
8434 /*@
8435    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8436 
8437    Not Collective
8438 
8439    Input Parameters:
8440 +  A - the matrix we wish to propagate options from
8441 -  B - the matrix we wish to propagate options to
8442 
8443    Level: beginner
8444 
8445    Note:
8446    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8447 
8448 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8449 @*/
8450 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8451 {
8452   PetscFunctionBegin;
8453   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8454   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8455   B->symmetry_eternal            = A->symmetry_eternal;
8456   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8457   B->symmetric                   = A->symmetric;
8458   B->structurally_symmetric      = A->structurally_symmetric;
8459   B->spd                         = A->spd;
8460   B->hermitian                   = A->hermitian;
8461   PetscFunctionReturn(PETSC_SUCCESS);
8462 }
8463 
8464 /*@
8465    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8466    used during the assembly process to store values that belong to
8467    other processors.
8468 
8469    Not Collective
8470 
8471    Input Parameters:
8472 +  mat   - the matrix
8473 .  size  - the initial size of the stash.
8474 -  bsize - the initial size of the block-stash(if used).
8475 
8476    Options Database Keys:
8477 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8478 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8479 
8480    Level: intermediate
8481 
8482    Notes:
8483      The block-stash is used for values set with `MatSetValuesBlocked()` while
8484      the stash is used for values set with `MatSetValues()`
8485 
8486      Run with the option -info and look for output of the form
8487      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8488      to determine the appropriate value, MM, to use for size and
8489      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8490      to determine the value, BMM to use for bsize
8491 
8492 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8493 @*/
8494 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8495 {
8496   PetscFunctionBegin;
8497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8498   PetscValidType(mat, 1);
8499   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8500   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8501   PetscFunctionReturn(PETSC_SUCCESS);
8502 }
8503 
8504 /*@
8505    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8506      the matrix
8507 
8508    Neighbor-wise Collective
8509 
8510    Input Parameters:
8511 +  mat   - the matrix
8512 .  x - the vector to be multiplied by the interpolation operator
8513 -  y - the vector to be added to the result
8514 
8515    Output Parameter:
8516 .  w - the resulting vector
8517 
8518    Level: intermediate
8519 
8520    Notes:
8521     `w` may be the same vector as `y`.
8522 
8523     This allows one to use either the restriction or interpolation (its transpose)
8524     matrix to do the interpolation
8525 
8526 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8527 @*/
8528 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8529 {
8530   PetscInt M, N, Ny;
8531 
8532   PetscFunctionBegin;
8533   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8534   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8535   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8536   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8537   PetscCall(MatGetSize(A, &M, &N));
8538   PetscCall(VecGetSize(y, &Ny));
8539   if (M == Ny) {
8540     PetscCall(MatMultAdd(A, x, y, w));
8541   } else {
8542     PetscCall(MatMultTransposeAdd(A, x, y, w));
8543   }
8544   PetscFunctionReturn(PETSC_SUCCESS);
8545 }
8546 
8547 /*@
8548    MatInterpolate - y = A*x or A'*x depending on the shape of
8549      the matrix
8550 
8551    Neighbor-wise Collective
8552 
8553    Input Parameters:
8554 +  mat   - the matrix
8555 -  x - the vector to be interpolated
8556 
8557    Output Parameter:
8558 .  y - the resulting vector
8559 
8560    Level: intermediate
8561 
8562    Note:
8563     This allows one to use either the restriction or interpolation (its transpose)
8564     matrix to do the interpolation
8565 
8566 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8567 @*/
8568 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8569 {
8570   PetscInt M, N, Ny;
8571 
8572   PetscFunctionBegin;
8573   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8574   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8575   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8576   PetscCall(MatGetSize(A, &M, &N));
8577   PetscCall(VecGetSize(y, &Ny));
8578   if (M == Ny) {
8579     PetscCall(MatMult(A, x, y));
8580   } else {
8581     PetscCall(MatMultTranspose(A, x, y));
8582   }
8583   PetscFunctionReturn(PETSC_SUCCESS);
8584 }
8585 
8586 /*@
8587    MatRestrict - y = A*x or A'*x
8588 
8589    Neighbor-wise Collective
8590 
8591    Input Parameters:
8592 +  mat   - the matrix
8593 -  x - the vector to be restricted
8594 
8595    Output Parameter:
8596 .  y - the resulting vector
8597 
8598    Level: intermediate
8599 
8600    Note:
8601     This allows one to use either the restriction or interpolation (its transpose)
8602     matrix to do the restriction
8603 
8604 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8605 @*/
8606 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8607 {
8608   PetscInt M, N, Ny;
8609 
8610   PetscFunctionBegin;
8611   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8612   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8613   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8614   PetscCall(MatGetSize(A, &M, &N));
8615   PetscCall(VecGetSize(y, &Ny));
8616   if (M == Ny) {
8617     PetscCall(MatMult(A, x, y));
8618   } else {
8619     PetscCall(MatMultTranspose(A, x, y));
8620   }
8621   PetscFunctionReturn(PETSC_SUCCESS);
8622 }
8623 
8624 /*@
8625    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8626 
8627    Neighbor-wise Collective
8628 
8629    Input Parameters:
8630 +  mat   - the matrix
8631 .  x - the input dense matrix to be multiplied
8632 -  w - the input dense matrix to be added to the result
8633 
8634    Output Parameter:
8635 .  y - the output dense matrix
8636 
8637    Level: intermediate
8638 
8639    Note:
8640     This allows one to use either the restriction or interpolation (its transpose)
8641     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8642     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8643 
8644 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8645 @*/
8646 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8647 {
8648   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8649   PetscBool trans = PETSC_TRUE;
8650   MatReuse  reuse = MAT_INITIAL_MATRIX;
8651 
8652   PetscFunctionBegin;
8653   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8654   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8655   PetscValidType(x, 2);
8656   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8657   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8658   PetscCall(MatGetSize(A, &M, &N));
8659   PetscCall(MatGetSize(x, &Mx, &Nx));
8660   if (N == Mx) trans = PETSC_FALSE;
8661   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);
8662   Mo = trans ? N : M;
8663   if (*y) {
8664     PetscCall(MatGetSize(*y, &My, &Ny));
8665     if (Mo == My && Nx == Ny) {
8666       reuse = MAT_REUSE_MATRIX;
8667     } else {
8668       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);
8669       PetscCall(MatDestroy(y));
8670     }
8671   }
8672 
8673   if (w && *y == w) { /* this is to minimize changes in PCMG */
8674     PetscBool flg;
8675 
8676     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8677     if (w) {
8678       PetscInt My, Ny, Mw, Nw;
8679 
8680       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8681       PetscCall(MatGetSize(*y, &My, &Ny));
8682       PetscCall(MatGetSize(w, &Mw, &Nw));
8683       if (!flg || My != Mw || Ny != Nw) w = NULL;
8684     }
8685     if (!w) {
8686       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8687       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8688       PetscCall(PetscObjectDereference((PetscObject)w));
8689     } else {
8690       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8691     }
8692   }
8693   if (!trans) {
8694     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8695   } else {
8696     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8697   }
8698   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8699   PetscFunctionReturn(PETSC_SUCCESS);
8700 }
8701 
8702 /*@
8703    MatMatInterpolate - Y = A*X or A'*X
8704 
8705    Neighbor-wise Collective
8706 
8707    Input Parameters:
8708 +  mat   - the matrix
8709 -  x - the input dense matrix
8710 
8711    Output Parameter:
8712 .  y - the output dense matrix
8713 
8714    Level: intermediate
8715 
8716    Note:
8717     This allows one to use either the restriction or interpolation (its transpose)
8718     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8719     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8720 
8721 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8722 @*/
8723 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8724 {
8725   PetscFunctionBegin;
8726   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8727   PetscFunctionReturn(PETSC_SUCCESS);
8728 }
8729 
8730 /*@
8731    MatMatRestrict - Y = A*X or A'*X
8732 
8733    Neighbor-wise Collective
8734 
8735    Input Parameters:
8736 +  mat   - the matrix
8737 -  x - the input dense matrix
8738 
8739    Output Parameter:
8740 .  y - the output dense matrix
8741 
8742    Level: intermediate
8743 
8744    Note:
8745     This allows one to use either the restriction or interpolation (its transpose)
8746     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8747     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8748 
8749 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8750 @*/
8751 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8752 {
8753   PetscFunctionBegin;
8754   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8755   PetscFunctionReturn(PETSC_SUCCESS);
8756 }
8757 
8758 /*@
8759    MatGetNullSpace - retrieves the null space of a matrix.
8760 
8761    Logically Collective
8762 
8763    Input Parameters:
8764 +  mat - the matrix
8765 -  nullsp - the null space object
8766 
8767    Level: developer
8768 
8769 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8770 @*/
8771 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8772 {
8773   PetscFunctionBegin;
8774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8775   PetscValidPointer(nullsp, 2);
8776   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8777   PetscFunctionReturn(PETSC_SUCCESS);
8778 }
8779 
8780 /*@
8781    MatSetNullSpace - attaches a null space to a matrix.
8782 
8783    Logically Collective
8784 
8785    Input Parameters:
8786 +  mat - the matrix
8787 -  nullsp - the null space object
8788 
8789    Level: advanced
8790 
8791    Notes:
8792       This null space is used by the `KSP` linear solvers to solve singular systems.
8793 
8794       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`
8795 
8796       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
8797       to zero but the linear system will still be solved in a least squares sense.
8798 
8799       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8800    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).
8801    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
8802    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
8803    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).
8804    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8805 
8806     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8807     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8808     routine also automatically calls `MatSetTransposeNullSpace()`.
8809 
8810     The user should call `MatNullSpaceDestroy()`.
8811 
8812 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8813           `KSPSetPCSide()`
8814 @*/
8815 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8816 {
8817   PetscFunctionBegin;
8818   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8819   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8820   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8821   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8822   mat->nullsp = nullsp;
8823   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8824   PetscFunctionReturn(PETSC_SUCCESS);
8825 }
8826 
8827 /*@
8828    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8829 
8830    Logically Collective
8831 
8832    Input Parameters:
8833 +  mat - the matrix
8834 -  nullsp - the null space object
8835 
8836    Level: developer
8837 
8838 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8839 @*/
8840 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8841 {
8842   PetscFunctionBegin;
8843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8844   PetscValidType(mat, 1);
8845   PetscValidPointer(nullsp, 2);
8846   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8847   PetscFunctionReturn(PETSC_SUCCESS);
8848 }
8849 
8850 /*@
8851    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8852 
8853    Logically Collective
8854 
8855    Input Parameters:
8856 +  mat - the matrix
8857 -  nullsp - the null space object
8858 
8859    Level: advanced
8860 
8861    Notes:
8862    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8863 
8864    See `MatSetNullSpace()`
8865 
8866 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8867 @*/
8868 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8869 {
8870   PetscFunctionBegin;
8871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8872   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8873   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8874   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8875   mat->transnullsp = nullsp;
8876   PetscFunctionReturn(PETSC_SUCCESS);
8877 }
8878 
8879 /*@
8880    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8881         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8882 
8883    Logically Collective
8884 
8885    Input Parameters:
8886 +  mat - the matrix
8887 -  nullsp - the null space object
8888 
8889    Level: advanced
8890 
8891    Notes:
8892    Overwrites any previous near null space that may have been attached
8893 
8894    You can remove the null space by calling this routine with an nullsp of `NULL`
8895 
8896 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8897 @*/
8898 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8899 {
8900   PetscFunctionBegin;
8901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8902   PetscValidType(mat, 1);
8903   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8904   MatCheckPreallocated(mat, 1);
8905   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8906   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8907   mat->nearnullsp = nullsp;
8908   PetscFunctionReturn(PETSC_SUCCESS);
8909 }
8910 
8911 /*@
8912    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8913 
8914    Not Collective
8915 
8916    Input Parameter:
8917 .  mat - the matrix
8918 
8919    Output Parameter:
8920 .  nullsp - the null space object, `NULL` if not set
8921 
8922    Level: advanced
8923 
8924 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8925 @*/
8926 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8927 {
8928   PetscFunctionBegin;
8929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8930   PetscValidType(mat, 1);
8931   PetscValidPointer(nullsp, 2);
8932   MatCheckPreallocated(mat, 1);
8933   *nullsp = mat->nearnullsp;
8934   PetscFunctionReturn(PETSC_SUCCESS);
8935 }
8936 
8937 /*@C
8938    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8939 
8940    Collective
8941 
8942    Input Parameters:
8943 +  mat - the matrix
8944 .  row - row/column permutation
8945 -  info - information on desired factorization process
8946 
8947    Level: developer
8948 
8949    Notes:
8950    Probably really in-place only when level of fill is zero, otherwise allocates
8951    new space to store factored matrix and deletes previous memory.
8952 
8953    Most users should employ the `KSP` interface for linear solvers
8954    instead of working directly with matrix algebra routines such as this.
8955    See, e.g., `KSPCreate()`.
8956 
8957    Developer Note:
8958    The Fortran interface is not autogenerated as the
8959    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8960 
8961 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8962 @*/
8963 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8964 {
8965   PetscFunctionBegin;
8966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8967   PetscValidType(mat, 1);
8968   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8969   PetscValidPointer(info, 3);
8970   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8971   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8972   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8973   MatCheckPreallocated(mat, 1);
8974   PetscUseTypeMethod(mat, iccfactor, row, info);
8975   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8976   PetscFunctionReturn(PETSC_SUCCESS);
8977 }
8978 
8979 /*@
8980    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8981          ghosted ones.
8982 
8983    Not Collective
8984 
8985    Input Parameters:
8986 +  mat - the matrix
8987 -  diag - the diagonal values, including ghost ones
8988 
8989    Level: developer
8990 
8991    Notes:
8992     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8993 
8994     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8995 
8996 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8997 @*/
8998 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8999 {
9000   PetscMPIInt size;
9001 
9002   PetscFunctionBegin;
9003   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9004   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9005   PetscValidType(mat, 1);
9006 
9007   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9008   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9009   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9010   if (size == 1) {
9011     PetscInt n, m;
9012     PetscCall(VecGetSize(diag, &n));
9013     PetscCall(MatGetSize(mat, NULL, &m));
9014     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9015     PetscCall(MatDiagonalScale(mat, NULL, diag));
9016   } else {
9017     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9018   }
9019   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9020   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9021   PetscFunctionReturn(PETSC_SUCCESS);
9022 }
9023 
9024 /*@
9025    MatGetInertia - Gets the inertia from a factored matrix
9026 
9027    Collective
9028 
9029    Input Parameter:
9030 .  mat - the matrix
9031 
9032    Output Parameters:
9033 +   nneg - number of negative eigenvalues
9034 .   nzero - number of zero eigenvalues
9035 -   npos - number of positive eigenvalues
9036 
9037    Level: advanced
9038 
9039    Note:
9040     Matrix must have been factored by `MatCholeskyFactor()`
9041 
9042 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9043 @*/
9044 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9045 {
9046   PetscFunctionBegin;
9047   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9048   PetscValidType(mat, 1);
9049   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9050   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9051   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9052   PetscFunctionReturn(PETSC_SUCCESS);
9053 }
9054 
9055 /*@C
9056    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9057 
9058    Neighbor-wise Collective
9059 
9060    Input Parameters:
9061 +  mat - the factored matrix obtained with `MatGetFactor()`
9062 -  b - the right-hand-side vectors
9063 
9064    Output Parameter:
9065 .  x - the result vectors
9066 
9067    Level: developer
9068 
9069    Note:
9070    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9071    call `MatSolves`(A,x,x).
9072 
9073 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9074 @*/
9075 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9076 {
9077   PetscFunctionBegin;
9078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9079   PetscValidType(mat, 1);
9080   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9081   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9082   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9083 
9084   MatCheckPreallocated(mat, 1);
9085   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9086   PetscUseTypeMethod(mat, solves, b, x);
9087   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9088   PetscFunctionReturn(PETSC_SUCCESS);
9089 }
9090 
9091 /*@
9092    MatIsSymmetric - Test whether a matrix is symmetric
9093 
9094    Collective
9095 
9096    Input Parameters:
9097 +  A - the matrix to test
9098 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9099 
9100    Output Parameter:
9101 .  flg - the result
9102 
9103    Level: intermediate
9104 
9105    Notes:
9106     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9107 
9108     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9109 
9110     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9111     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9112 
9113 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9114           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9115 @*/
9116 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9117 {
9118   PetscFunctionBegin;
9119   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9120   PetscValidBoolPointer(flg, 3);
9121 
9122   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9123   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9124   else {
9125     if (!A->ops->issymmetric) {
9126       MatType mattype;
9127       PetscCall(MatGetType(A, &mattype));
9128       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9129     }
9130     PetscUseTypeMethod(A, issymmetric, tol, flg);
9131     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9132   }
9133   PetscFunctionReturn(PETSC_SUCCESS);
9134 }
9135 
9136 /*@
9137    MatIsHermitian - Test whether a matrix is Hermitian
9138 
9139    Collective
9140 
9141    Input Parameters:
9142 +  A - the matrix to test
9143 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9144 
9145    Output Parameter:
9146 .  flg - the result
9147 
9148    Level: intermediate
9149 
9150    Notes:
9151     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9152 
9153     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9154 
9155     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9156     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9157 
9158 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9159           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9160 @*/
9161 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9162 {
9163   PetscFunctionBegin;
9164   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9165   PetscValidBoolPointer(flg, 3);
9166 
9167   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9168   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9169   else {
9170     if (!A->ops->ishermitian) {
9171       MatType mattype;
9172       PetscCall(MatGetType(A, &mattype));
9173       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9174     }
9175     PetscUseTypeMethod(A, ishermitian, tol, flg);
9176     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9177   }
9178   PetscFunctionReturn(PETSC_SUCCESS);
9179 }
9180 
9181 /*@
9182    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9183 
9184    Not Collective
9185 
9186    Input Parameter:
9187 .  A - the matrix to check
9188 
9189    Output Parameters:
9190 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9191 -  flg - the result (only valid if set is `PETSC_TRUE`)
9192 
9193    Level: advanced
9194 
9195    Notes:
9196    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9197    if you want it explicitly checked
9198 
9199     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9200     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9201 
9202 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9203 @*/
9204 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9205 {
9206   PetscFunctionBegin;
9207   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9208   PetscValidBoolPointer(set, 2);
9209   PetscValidBoolPointer(flg, 3);
9210   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9211     *set = PETSC_TRUE;
9212     *flg = PetscBool3ToBool(A->symmetric);
9213   } else {
9214     *set = PETSC_FALSE;
9215   }
9216   PetscFunctionReturn(PETSC_SUCCESS);
9217 }
9218 
9219 /*@
9220    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9221 
9222    Not Collective
9223 
9224    Input Parameter:
9225 .  A - the matrix to check
9226 
9227    Output Parameters:
9228 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9229 -  flg - the result (only valid if set is `PETSC_TRUE`)
9230 
9231    Level: advanced
9232 
9233    Notes:
9234    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9235 
9236    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9237    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9238 
9239 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9240 @*/
9241 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9242 {
9243   PetscFunctionBegin;
9244   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9245   PetscValidBoolPointer(set, 2);
9246   PetscValidBoolPointer(flg, 3);
9247   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9248     *set = PETSC_TRUE;
9249     *flg = PetscBool3ToBool(A->spd);
9250   } else {
9251     *set = PETSC_FALSE;
9252   }
9253   PetscFunctionReturn(PETSC_SUCCESS);
9254 }
9255 
9256 /*@
9257    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9258 
9259    Not Collective
9260 
9261    Input Parameter:
9262 .  A - the matrix to check
9263 
9264    Output Parameters:
9265 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9266 -  flg - the result (only valid if set is `PETSC_TRUE`)
9267 
9268    Level: advanced
9269 
9270    Notes:
9271    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9272    if you want it explicitly checked
9273 
9274    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9275    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9276 
9277 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9278 @*/
9279 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9280 {
9281   PetscFunctionBegin;
9282   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9283   PetscValidBoolPointer(set, 2);
9284   PetscValidBoolPointer(flg, 3);
9285   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9286     *set = PETSC_TRUE;
9287     *flg = PetscBool3ToBool(A->hermitian);
9288   } else {
9289     *set = PETSC_FALSE;
9290   }
9291   PetscFunctionReturn(PETSC_SUCCESS);
9292 }
9293 
9294 /*@
9295    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9296 
9297    Collective
9298 
9299    Input Parameter:
9300 .  A - the matrix to test
9301 
9302    Output Parameter:
9303 .  flg - the result
9304 
9305    Level: intermediate
9306 
9307    Notes:
9308    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9309 
9310    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9311    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9312 
9313 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9314 @*/
9315 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9316 {
9317   PetscFunctionBegin;
9318   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9319   PetscValidBoolPointer(flg, 2);
9320   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9321     *flg = PetscBool3ToBool(A->structurally_symmetric);
9322   } else {
9323     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9324     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9325   }
9326   PetscFunctionReturn(PETSC_SUCCESS);
9327 }
9328 
9329 /*@
9330    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9331 
9332    Not Collective
9333 
9334    Input Parameter:
9335 .  A - the matrix to check
9336 
9337    Output Parameters:
9338 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9339 -  flg - the result (only valid if set is PETSC_TRUE)
9340 
9341    Level: advanced
9342 
9343    Notes:
9344    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9345    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9346 
9347    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9348 
9349 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9350 @*/
9351 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9352 {
9353   PetscFunctionBegin;
9354   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9355   PetscValidBoolPointer(set, 2);
9356   PetscValidBoolPointer(flg, 3);
9357   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9358     *set = PETSC_TRUE;
9359     *flg = PetscBool3ToBool(A->structurally_symmetric);
9360   } else {
9361     *set = PETSC_FALSE;
9362   }
9363   PetscFunctionReturn(PETSC_SUCCESS);
9364 }
9365 
9366 /*@
9367    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9368        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9369 
9370     Not Collective
9371 
9372    Input Parameter:
9373 .   mat - the matrix
9374 
9375    Output Parameters:
9376 +   nstash   - the size of the stash
9377 .   reallocs - the number of additional mallocs incurred.
9378 .   bnstash   - the size of the block stash
9379 -   breallocs - the number of additional mallocs incurred.in the block stash
9380 
9381    Level: advanced
9382 
9383 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9384 @*/
9385 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9386 {
9387   PetscFunctionBegin;
9388   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9389   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9390   PetscFunctionReturn(PETSC_SUCCESS);
9391 }
9392 
9393 /*@C
9394    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9395    parallel layout, `PetscLayout` for rows and columns
9396 
9397    Collective
9398 
9399    Input Parameter:
9400 .  mat - the matrix
9401 
9402    Output Parameters:
9403 +   right - (optional) vector that the matrix can be multiplied against
9404 -   left - (optional) vector that the matrix vector product can be stored in
9405 
9406   Level: advanced
9407 
9408    Notes:
9409     The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.
9410 
9411     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9412 
9413 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9414 @*/
9415 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9416 {
9417   PetscFunctionBegin;
9418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9419   PetscValidType(mat, 1);
9420   if (mat->ops->getvecs) {
9421     PetscUseTypeMethod(mat, getvecs, right, left);
9422   } else {
9423     PetscInt rbs, cbs;
9424     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9425     if (right) {
9426       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9427       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9428       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9429       PetscCall(VecSetBlockSize(*right, cbs));
9430       PetscCall(VecSetType(*right, mat->defaultvectype));
9431 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9432       if (mat->boundtocpu && mat->bindingpropagates) {
9433         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9434         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9435       }
9436 #endif
9437       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9438     }
9439     if (left) {
9440       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9441       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9442       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9443       PetscCall(VecSetBlockSize(*left, rbs));
9444       PetscCall(VecSetType(*left, mat->defaultvectype));
9445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9446       if (mat->boundtocpu && mat->bindingpropagates) {
9447         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9448         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9449       }
9450 #endif
9451       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9452     }
9453   }
9454   PetscFunctionReturn(PETSC_SUCCESS);
9455 }
9456 
9457 /*@C
9458    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9459      with default values.
9460 
9461    Not Collective
9462 
9463    Input Parameter:
9464 .    info - the `MatFactorInfo` data structure
9465 
9466    Level: developer
9467 
9468    Notes:
9469     The solvers are generally used through the `KSP` and `PC` objects, for example
9470           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9471 
9472     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9473 
9474    Developer Note:
9475    The Fortran interface is not autogenerated as the
9476    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9477 
9478 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9479 @*/
9480 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9481 {
9482   PetscFunctionBegin;
9483   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9484   PetscFunctionReturn(PETSC_SUCCESS);
9485 }
9486 
9487 /*@
9488    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9489 
9490    Collective
9491 
9492    Input Parameters:
9493 +  mat - the factored matrix
9494 -  is - the index set defining the Schur indices (0-based)
9495 
9496    Level: advanced
9497 
9498    Notes:
9499     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9500 
9501    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9502 
9503    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9504 
9505 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9506           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9507 @*/
9508 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9509 {
9510   PetscErrorCode (*f)(Mat, IS);
9511 
9512   PetscFunctionBegin;
9513   PetscValidType(mat, 1);
9514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9515   PetscValidType(is, 2);
9516   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9517   PetscCheckSameComm(mat, 1, is, 2);
9518   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9519   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9520   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9521   PetscCall(MatDestroy(&mat->schur));
9522   PetscCall((*f)(mat, is));
9523   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9524   PetscFunctionReturn(PETSC_SUCCESS);
9525 }
9526 
9527 /*@
9528   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9529 
9530    Logically Collective
9531 
9532    Input Parameters:
9533 +  F - the factored matrix obtained by calling `MatGetFactor()`
9534 .  S - location where to return the Schur complement, can be `NULL`
9535 -  status - the status of the Schur complement matrix, can be `NULL`
9536 
9537    Level: advanced
9538 
9539    Notes:
9540    You must call `MatFactorSetSchurIS()` before calling this routine.
9541 
9542    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9543 
9544    The routine provides a copy of the Schur matrix stored within the solver data structures.
9545    The caller must destroy the object when it is no longer needed.
9546    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9547 
9548    Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)
9549 
9550    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9551 
9552    Developer Note:
9553     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9554    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9555 
9556 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9557 @*/
9558 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9559 {
9560   PetscFunctionBegin;
9561   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9562   if (S) PetscValidPointer(S, 2);
9563   if (status) PetscValidPointer(status, 3);
9564   if (S) {
9565     PetscErrorCode (*f)(Mat, Mat *);
9566 
9567     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9568     if (f) {
9569       PetscCall((*f)(F, S));
9570     } else {
9571       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9572     }
9573   }
9574   if (status) *status = F->schur_status;
9575   PetscFunctionReturn(PETSC_SUCCESS);
9576 }
9577 
9578 /*@
9579   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9580 
9581    Logically Collective
9582 
9583    Input Parameters:
9584 +  F - the factored matrix obtained by calling `MatGetFactor()`
9585 .  *S - location where to return the Schur complement, can be `NULL`
9586 -  status - the status of the Schur complement matrix, can be `NULL`
9587 
9588    Level: advanced
9589 
9590    Notes:
9591    You must call `MatFactorSetSchurIS()` before calling this routine.
9592 
9593    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9594 
9595    The routine returns a the Schur Complement stored within the data structures of the solver.
9596 
9597    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9598 
9599    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9600 
9601    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9602 
9603    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9604 
9605 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9606 @*/
9607 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9608 {
9609   PetscFunctionBegin;
9610   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9611   if (S) PetscValidPointer(S, 2);
9612   if (status) PetscValidPointer(status, 3);
9613   if (S) *S = F->schur;
9614   if (status) *status = F->schur_status;
9615   PetscFunctionReturn(PETSC_SUCCESS);
9616 }
9617 
9618 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9619 {
9620   Mat S = F->schur;
9621 
9622   PetscFunctionBegin;
9623   switch (F->schur_status) {
9624   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9625   case MAT_FACTOR_SCHUR_INVERTED:
9626     if (S) {
9627       S->ops->solve             = NULL;
9628       S->ops->matsolve          = NULL;
9629       S->ops->solvetranspose    = NULL;
9630       S->ops->matsolvetranspose = NULL;
9631       S->ops->solveadd          = NULL;
9632       S->ops->solvetransposeadd = NULL;
9633       S->factortype             = MAT_FACTOR_NONE;
9634       PetscCall(PetscFree(S->solvertype));
9635     }
9636   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9637     break;
9638   default:
9639     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9640   }
9641   PetscFunctionReturn(PETSC_SUCCESS);
9642 }
9643 
9644 /*@
9645   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9646 
9647    Logically Collective
9648 
9649    Input Parameters:
9650 +  F - the factored matrix obtained by calling `MatGetFactor()`
9651 .  *S - location where the Schur complement is stored
9652 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9653 
9654    Level: advanced
9655 
9656 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9657 @*/
9658 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9659 {
9660   PetscFunctionBegin;
9661   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9662   if (S) {
9663     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9664     *S = NULL;
9665   }
9666   F->schur_status = status;
9667   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9668   PetscFunctionReturn(PETSC_SUCCESS);
9669 }
9670 
9671 /*@
9672   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9673 
9674    Logically Collective
9675 
9676    Input Parameters:
9677 +  F - the factored matrix obtained by calling `MatGetFactor()`
9678 .  rhs - location where the right hand side of the Schur complement system is stored
9679 -  sol - location where the solution of the Schur complement system has to be returned
9680 
9681    Level: advanced
9682 
9683    Notes:
9684    The sizes of the vectors should match the size of the Schur complement
9685 
9686    Must be called after `MatFactorSetSchurIS()`
9687 
9688 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9689 @*/
9690 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9691 {
9692   PetscFunctionBegin;
9693   PetscValidType(F, 1);
9694   PetscValidType(rhs, 2);
9695   PetscValidType(sol, 3);
9696   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9697   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9698   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9699   PetscCheckSameComm(F, 1, rhs, 2);
9700   PetscCheckSameComm(F, 1, sol, 3);
9701   PetscCall(MatFactorFactorizeSchurComplement(F));
9702   switch (F->schur_status) {
9703   case MAT_FACTOR_SCHUR_FACTORED:
9704     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9705     break;
9706   case MAT_FACTOR_SCHUR_INVERTED:
9707     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9708     break;
9709   default:
9710     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9711   }
9712   PetscFunctionReturn(PETSC_SUCCESS);
9713 }
9714 
9715 /*@
9716   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9717 
9718    Logically Collective
9719 
9720    Input Parameters:
9721 +  F - the factored matrix obtained by calling `MatGetFactor()`
9722 .  rhs - location where the right hand side of the Schur complement system is stored
9723 -  sol - location where the solution of the Schur complement system has to be returned
9724 
9725    Level: advanced
9726 
9727    Notes:
9728    The sizes of the vectors should match the size of the Schur complement
9729 
9730    Must be called after `MatFactorSetSchurIS()`
9731 
9732 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9733 @*/
9734 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9735 {
9736   PetscFunctionBegin;
9737   PetscValidType(F, 1);
9738   PetscValidType(rhs, 2);
9739   PetscValidType(sol, 3);
9740   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9741   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9742   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9743   PetscCheckSameComm(F, 1, rhs, 2);
9744   PetscCheckSameComm(F, 1, sol, 3);
9745   PetscCall(MatFactorFactorizeSchurComplement(F));
9746   switch (F->schur_status) {
9747   case MAT_FACTOR_SCHUR_FACTORED:
9748     PetscCall(MatSolve(F->schur, rhs, sol));
9749     break;
9750   case MAT_FACTOR_SCHUR_INVERTED:
9751     PetscCall(MatMult(F->schur, rhs, sol));
9752     break;
9753   default:
9754     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9755   }
9756   PetscFunctionReturn(PETSC_SUCCESS);
9757 }
9758 
9759 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9760 #if PetscDefined(HAVE_CUDA)
9761 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9762 #endif
9763 
9764 /* Schur status updated in the interface */
9765 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9766 {
9767   Mat S = F->schur;
9768 
9769   PetscFunctionBegin;
9770   if (S) {
9771     PetscMPIInt size;
9772     PetscBool   isdense, isdensecuda;
9773 
9774     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9775     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9776     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9777     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9778     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9779     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9780     if (isdense) {
9781       PetscCall(MatSeqDenseInvertFactors_Private(S));
9782     } else if (isdensecuda) {
9783 #if defined(PETSC_HAVE_CUDA)
9784       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9785 #endif
9786     }
9787     // HIP??????????????
9788     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9789   }
9790   PetscFunctionReturn(PETSC_SUCCESS);
9791 }
9792 
9793 /*@
9794   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9795 
9796    Logically Collective
9797 
9798    Input Parameter:
9799 .  F - the factored matrix obtained by calling `MatGetFactor()`
9800 
9801    Level: advanced
9802 
9803    Notes:
9804     Must be called after `MatFactorSetSchurIS()`.
9805 
9806    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9807 
9808 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9809 @*/
9810 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9811 {
9812   PetscFunctionBegin;
9813   PetscValidType(F, 1);
9814   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9815   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9816   PetscCall(MatFactorFactorizeSchurComplement(F));
9817   PetscCall(MatFactorInvertSchurComplement_Private(F));
9818   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9819   PetscFunctionReturn(PETSC_SUCCESS);
9820 }
9821 
9822 /*@
9823   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9824 
9825    Logically Collective
9826 
9827    Input Parameter:
9828 .  F - the factored matrix obtained by calling `MatGetFactor()`
9829 
9830    Level: advanced
9831 
9832    Note:
9833     Must be called after `MatFactorSetSchurIS()`
9834 
9835 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9836 @*/
9837 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9838 {
9839   MatFactorInfo info;
9840 
9841   PetscFunctionBegin;
9842   PetscValidType(F, 1);
9843   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9844   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9845   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9846   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9847   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9848     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9849   } else {
9850     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9851   }
9852   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9853   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9854   PetscFunctionReturn(PETSC_SUCCESS);
9855 }
9856 
9857 /*@
9858    MatPtAP - Creates the matrix product C = P^T * A * P
9859 
9860    Neighbor-wise Collective
9861 
9862    Input Parameters:
9863 +  A - the matrix
9864 .  P - the projection matrix
9865 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9866 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9867           if the result is a dense matrix this is irrelevant
9868 
9869    Output Parameter:
9870 .  C - the product matrix
9871 
9872    Level: intermediate
9873 
9874    Notes:
9875    C will be created and must be destroyed by the user with `MatDestroy()`.
9876 
9877    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9878 
9879    Developer Note:
9880    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9881 
9882 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9883 @*/
9884 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9885 {
9886   PetscFunctionBegin;
9887   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9888   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9889 
9890   if (scall == MAT_INITIAL_MATRIX) {
9891     PetscCall(MatProductCreate(A, P, NULL, C));
9892     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9893     PetscCall(MatProductSetAlgorithm(*C, "default"));
9894     PetscCall(MatProductSetFill(*C, fill));
9895 
9896     (*C)->product->api_user = PETSC_TRUE;
9897     PetscCall(MatProductSetFromOptions(*C));
9898     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and P %s", MatProductTypes[MATPRODUCT_PtAP], ((PetscObject)A)->type_name, ((PetscObject)P)->type_name);
9899     PetscCall(MatProductSymbolic(*C));
9900   } else { /* scall == MAT_REUSE_MATRIX */
9901     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9902   }
9903 
9904   PetscCall(MatProductNumeric(*C));
9905   (*C)->symmetric = A->symmetric;
9906   (*C)->spd       = A->spd;
9907   PetscFunctionReturn(PETSC_SUCCESS);
9908 }
9909 
9910 /*@
9911    MatRARt - Creates the matrix product C = R * A * R^T
9912 
9913    Neighbor-wise Collective
9914 
9915    Input Parameters:
9916 +  A - the matrix
9917 .  R - the projection matrix
9918 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9919 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9920           if the result is a dense matrix this is irrelevant
9921 
9922    Output Parameter:
9923 .  C - the product matrix
9924 
9925    Level: intermediate
9926 
9927    Notes:
9928    C will be created and must be destroyed by the user with `MatDestroy()`.
9929 
9930    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9931 
9932    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9933    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9934    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9935    We recommend using MatPtAP().
9936 
9937 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9938 @*/
9939 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9940 {
9941   PetscFunctionBegin;
9942   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9943   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9944 
9945   if (scall == MAT_INITIAL_MATRIX) {
9946     PetscCall(MatProductCreate(A, R, NULL, C));
9947     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9948     PetscCall(MatProductSetAlgorithm(*C, "default"));
9949     PetscCall(MatProductSetFill(*C, fill));
9950 
9951     (*C)->product->api_user = PETSC_TRUE;
9952     PetscCall(MatProductSetFromOptions(*C));
9953     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name);
9954     PetscCall(MatProductSymbolic(*C));
9955   } else { /* scall == MAT_REUSE_MATRIX */
9956     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9957   }
9958 
9959   PetscCall(MatProductNumeric(*C));
9960   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9961   PetscFunctionReturn(PETSC_SUCCESS);
9962 }
9963 
9964 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9965 {
9966   PetscFunctionBegin;
9967   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9968 
9969   if (scall == MAT_INITIAL_MATRIX) {
9970     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9971     PetscCall(MatProductCreate(A, B, NULL, C));
9972     PetscCall(MatProductSetType(*C, ptype));
9973     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9974     PetscCall(MatProductSetFill(*C, fill));
9975 
9976     (*C)->product->api_user = PETSC_TRUE;
9977     PetscCall(MatProductSetFromOptions(*C));
9978     PetscCall(MatProductSymbolic(*C));
9979   } else { /* scall == MAT_REUSE_MATRIX */
9980     Mat_Product *product = (*C)->product;
9981     PetscBool    isdense;
9982 
9983     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9984     if (isdense && product && product->type != ptype) {
9985       PetscCall(MatProductClear(*C));
9986       product = NULL;
9987     }
9988     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9989     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9990       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9991       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9992       product           = (*C)->product;
9993       product->fill     = fill;
9994       product->api_user = PETSC_TRUE;
9995       product->clear    = PETSC_TRUE;
9996 
9997       PetscCall(MatProductSetType(*C, ptype));
9998       PetscCall(MatProductSetFromOptions(*C));
9999       PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name);
10000       PetscCall(MatProductSymbolic(*C));
10001     } else { /* user may change input matrices A or B when REUSE */
10002       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10003     }
10004   }
10005   PetscCall(MatProductNumeric(*C));
10006   PetscFunctionReturn(PETSC_SUCCESS);
10007 }
10008 
10009 /*@
10010    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10011 
10012    Neighbor-wise Collective
10013 
10014    Input Parameters:
10015 +  A - the left matrix
10016 .  B - the right matrix
10017 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10018 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10019           if the result is a dense matrix this is irrelevant
10020 
10021    Output Parameter:
10022 .  C - the product matrix
10023 
10024    Notes:
10025    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10026 
10027    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
10028    call to this function with `MAT_INITIAL_MATRIX`.
10029 
10030    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10031 
10032    In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
10033    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10034 
10035    Example of Usage:
10036 .vb
10037      MatProductCreate(A,B,NULL,&C);
10038      MatProductSetType(C,MATPRODUCT_AB);
10039      MatProductSymbolic(C);
10040      MatProductNumeric(C); // compute C=A * B
10041      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10042      MatProductNumeric(C);
10043      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10044      MatProductNumeric(C);
10045 .ve
10046 
10047    Level: intermediate
10048 
10049 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10050 @*/
10051 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10052 {
10053   PetscFunctionBegin;
10054   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10055   PetscFunctionReturn(PETSC_SUCCESS);
10056 }
10057 
10058 /*@
10059    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10060 
10061    Neighbor-wise Collective
10062 
10063    Input Parameters:
10064 +  A - the left matrix
10065 .  B - the right matrix
10066 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10067 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10068 
10069    Output Parameter:
10070 .  C - the product matrix
10071 
10072    Level: intermediate
10073 
10074    Notes:
10075    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10076 
10077    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10078 
10079    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10080    actually needed.
10081 
10082    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10083    and for pairs of `MATMPIDENSE` matrices.
10084 
10085    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10086 
10087    Options Database Keys:
10088 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10089               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10090               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10091 
10092 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10093 @*/
10094 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10095 {
10096   PetscFunctionBegin;
10097   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10098   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10099   PetscFunctionReturn(PETSC_SUCCESS);
10100 }
10101 
10102 /*@
10103    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10104 
10105    Neighbor-wise Collective
10106 
10107    Input Parameters:
10108 +  A - the left matrix
10109 .  B - the right matrix
10110 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10111 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10112 
10113    Output Parameter:
10114 .  C - the product matrix
10115 
10116    Level: intermediate
10117 
10118    Notes:
10119    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10120 
10121    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10122 
10123    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10124 
10125    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10126    actually needed.
10127 
10128    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10129    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10130 
10131 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10132 @*/
10133 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10134 {
10135   PetscFunctionBegin;
10136   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10137   PetscFunctionReturn(PETSC_SUCCESS);
10138 }
10139 
10140 /*@
10141    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10142 
10143    Neighbor-wise Collective
10144 
10145    Input Parameters:
10146 +  A - the left matrix
10147 .  B - the middle matrix
10148 .  C - the right matrix
10149 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10150 -  fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
10151           if the result is a dense matrix this is irrelevant
10152 
10153    Output Parameter:
10154 .  D - the product matrix
10155 
10156    Level: intermediate
10157 
10158    Notes:
10159    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10160 
10161    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10162 
10163    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10164 
10165    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10166    actually needed.
10167 
10168    If you have many matrices with the same non-zero structure to multiply, you
10169    should use `MAT_REUSE_MATRIX` in all calls but the first
10170 
10171 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10172 @*/
10173 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10174 {
10175   PetscFunctionBegin;
10176   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10177   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10178 
10179   if (scall == MAT_INITIAL_MATRIX) {
10180     PetscCall(MatProductCreate(A, B, C, D));
10181     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10182     PetscCall(MatProductSetAlgorithm(*D, "default"));
10183     PetscCall(MatProductSetFill(*D, fill));
10184 
10185     (*D)->product->api_user = PETSC_TRUE;
10186     PetscCall(MatProductSetFromOptions(*D));
10187     PetscCheck((*D)->ops->productsymbolic, PetscObjectComm((PetscObject)(*D)), PETSC_ERR_SUP, "MatProduct %s not supported for A %s, B %s and C %s", MatProductTypes[MATPRODUCT_ABC], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name,
10188                ((PetscObject)C)->type_name);
10189     PetscCall(MatProductSymbolic(*D));
10190   } else { /* user may change input matrices when REUSE */
10191     PetscCall(MatProductReplaceMats(A, B, C, *D));
10192   }
10193   PetscCall(MatProductNumeric(*D));
10194   PetscFunctionReturn(PETSC_SUCCESS);
10195 }
10196 
10197 /*@
10198    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10199 
10200    Collective
10201 
10202    Input Parameters:
10203 +  mat - the matrix
10204 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10205 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10206 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10207 
10208    Output Parameter:
10209 .  matredundant - redundant matrix
10210 
10211    Level: advanced
10212 
10213    Notes:
10214    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10215    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10216 
10217    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10218    calling it.
10219 
10220    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10221 
10222 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10223 @*/
10224 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10225 {
10226   MPI_Comm       comm;
10227   PetscMPIInt    size;
10228   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10229   Mat_Redundant *redund     = NULL;
10230   PetscSubcomm   psubcomm   = NULL;
10231   MPI_Comm       subcomm_in = subcomm;
10232   Mat           *matseq;
10233   IS             isrow, iscol;
10234   PetscBool      newsubcomm = PETSC_FALSE;
10235 
10236   PetscFunctionBegin;
10237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10238   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10239     PetscValidPointer(*matredundant, 5);
10240     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10241   }
10242 
10243   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10244   if (size == 1 || nsubcomm == 1) {
10245     if (reuse == MAT_INITIAL_MATRIX) {
10246       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10247     } else {
10248       PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10249       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10250     }
10251     PetscFunctionReturn(PETSC_SUCCESS);
10252   }
10253 
10254   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10255   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10256   MatCheckPreallocated(mat, 1);
10257 
10258   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10259   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10260     /* create psubcomm, then get subcomm */
10261     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10262     PetscCallMPI(MPI_Comm_size(comm, &size));
10263     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10264 
10265     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10266     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10267     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10268     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10269     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10270     newsubcomm = PETSC_TRUE;
10271     PetscCall(PetscSubcommDestroy(&psubcomm));
10272   }
10273 
10274   /* get isrow, iscol and a local sequential matrix matseq[0] */
10275   if (reuse == MAT_INITIAL_MATRIX) {
10276     mloc_sub = PETSC_DECIDE;
10277     nloc_sub = PETSC_DECIDE;
10278     if (bs < 1) {
10279       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10280       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10281     } else {
10282       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10283       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10284     }
10285     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10286     rstart = rend - mloc_sub;
10287     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10288     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10289   } else { /* reuse == MAT_REUSE_MATRIX */
10290     PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10291     /* retrieve subcomm */
10292     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10293     redund = (*matredundant)->redundant;
10294     isrow  = redund->isrow;
10295     iscol  = redund->iscol;
10296     matseq = redund->matseq;
10297   }
10298   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10299 
10300   /* get matredundant over subcomm */
10301   if (reuse == MAT_INITIAL_MATRIX) {
10302     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10303 
10304     /* create a supporting struct and attach it to C for reuse */
10305     PetscCall(PetscNew(&redund));
10306     (*matredundant)->redundant = redund;
10307     redund->isrow              = isrow;
10308     redund->iscol              = iscol;
10309     redund->matseq             = matseq;
10310     if (newsubcomm) {
10311       redund->subcomm = subcomm;
10312     } else {
10313       redund->subcomm = MPI_COMM_NULL;
10314     }
10315   } else {
10316     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10317   }
10318 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10319   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10320     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10321     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10322   }
10323 #endif
10324   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10325   PetscFunctionReturn(PETSC_SUCCESS);
10326 }
10327 
10328 /*@C
10329    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10330    a given `Mat`. Each submatrix can span multiple procs.
10331 
10332    Collective
10333 
10334    Input Parameters:
10335 +  mat - the matrix
10336 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10337 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10338 
10339    Output Parameter:
10340 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10341 
10342   Level: advanced
10343 
10344   Notes:
10345   The submatrix partition across processors is dictated by `subComm` a
10346   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10347   is not restricted to be grouped with consecutive original ranks.
10348 
10349   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10350   map directly to the layout of the original matrix [wrt the local
10351   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10352   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10353   the `subMat`. However the offDiagMat looses some columns - and this is
10354   reconstructed with `MatSetValues()`
10355 
10356   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10357 
10358 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10359 @*/
10360 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10361 {
10362   PetscMPIInt commsize, subCommSize;
10363 
10364   PetscFunctionBegin;
10365   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10366   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10367   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10368 
10369   PetscCheck(scall != MAT_REUSE_MATRIX || *subMat != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix");
10370   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10371   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10372   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10373   PetscFunctionReturn(PETSC_SUCCESS);
10374 }
10375 
10376 /*@
10377    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10378 
10379    Not Collective
10380 
10381    Input Parameters:
10382 +  mat - matrix to extract local submatrix from
10383 .  isrow - local row indices for submatrix
10384 -  iscol - local column indices for submatrix
10385 
10386    Output Parameter:
10387 .  submat - the submatrix
10388 
10389    Level: intermediate
10390 
10391    Notes:
10392    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10393 
10394    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10395    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10396 
10397    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10398    `MatSetValuesBlockedLocal()` will also be implemented.
10399 
10400    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10401    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10402 
10403 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10404 @*/
10405 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10406 {
10407   PetscFunctionBegin;
10408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10409   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10410   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10411   PetscCheckSameComm(isrow, 2, iscol, 3);
10412   PetscValidPointer(submat, 4);
10413   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10414 
10415   if (mat->ops->getlocalsubmatrix) {
10416     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10417   } else {
10418     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10419   }
10420   PetscFunctionReturn(PETSC_SUCCESS);
10421 }
10422 
10423 /*@
10424    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10425 
10426    Not Collective
10427 
10428    Input Parameters:
10429 +  mat - matrix to extract local submatrix from
10430 .  isrow - local row indices for submatrix
10431 .  iscol - local column indices for submatrix
10432 -  submat - the submatrix
10433 
10434    Level: intermediate
10435 
10436 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10437 @*/
10438 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10439 {
10440   PetscFunctionBegin;
10441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10442   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10443   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10444   PetscCheckSameComm(isrow, 2, iscol, 3);
10445   PetscValidPointer(submat, 4);
10446   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10447 
10448   if (mat->ops->restorelocalsubmatrix) {
10449     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10450   } else {
10451     PetscCall(MatDestroy(submat));
10452   }
10453   *submat = NULL;
10454   PetscFunctionReturn(PETSC_SUCCESS);
10455 }
10456 
10457 /*@
10458    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10459 
10460    Collective
10461 
10462    Input Parameter:
10463 .  mat - the matrix
10464 
10465    Output Parameter:
10466 .  is - if any rows have zero diagonals this contains the list of them
10467 
10468    Level: developer
10469 
10470 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10471 @*/
10472 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10473 {
10474   PetscFunctionBegin;
10475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10476   PetscValidType(mat, 1);
10477   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10478   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10479 
10480   if (!mat->ops->findzerodiagonals) {
10481     Vec                diag;
10482     const PetscScalar *a;
10483     PetscInt          *rows;
10484     PetscInt           rStart, rEnd, r, nrow = 0;
10485 
10486     PetscCall(MatCreateVecs(mat, &diag, NULL));
10487     PetscCall(MatGetDiagonal(mat, diag));
10488     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10489     PetscCall(VecGetArrayRead(diag, &a));
10490     for (r = 0; r < rEnd - rStart; ++r)
10491       if (a[r] == 0.0) ++nrow;
10492     PetscCall(PetscMalloc1(nrow, &rows));
10493     nrow = 0;
10494     for (r = 0; r < rEnd - rStart; ++r)
10495       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10496     PetscCall(VecRestoreArrayRead(diag, &a));
10497     PetscCall(VecDestroy(&diag));
10498     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10499   } else {
10500     PetscUseTypeMethod(mat, findzerodiagonals, is);
10501   }
10502   PetscFunctionReturn(PETSC_SUCCESS);
10503 }
10504 
10505 /*@
10506    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10507 
10508    Collective
10509 
10510    Input Parameter:
10511 .  mat - the matrix
10512 
10513    Output Parameter:
10514 .  is - contains the list of rows with off block diagonal entries
10515 
10516    Level: developer
10517 
10518 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10519 @*/
10520 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10521 {
10522   PetscFunctionBegin;
10523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10524   PetscValidType(mat, 1);
10525   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10526   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10527 
10528   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10529   PetscFunctionReturn(PETSC_SUCCESS);
10530 }
10531 
10532 /*@C
10533   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10534 
10535   Collective; No Fortran Support
10536 
10537   Input Parameter:
10538 . mat - the matrix
10539 
10540   Output Parameter:
10541 . values - the block inverses in column major order (FORTRAN-like)
10542 
10543   Level: advanced
10544 
10545    Notes:
10546    The size of the blocks is determined by the block size of the matrix.
10547 
10548    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10549 
10550    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10551 
10552 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10553 @*/
10554 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10555 {
10556   PetscFunctionBegin;
10557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10558   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10559   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10560   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10561   PetscFunctionReturn(PETSC_SUCCESS);
10562 }
10563 
10564 /*@C
10565   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10566 
10567   Collective; No Fortran Support
10568 
10569   Input Parameters:
10570 + mat - the matrix
10571 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10572 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10573 
10574   Output Parameter:
10575 . values - the block inverses in column major order (FORTRAN-like)
10576 
10577   Level: advanced
10578 
10579   Notes:
10580   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10581 
10582   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10583 
10584 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10585 @*/
10586 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10587 {
10588   PetscFunctionBegin;
10589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10590   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10591   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10592   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10593   PetscFunctionReturn(PETSC_SUCCESS);
10594 }
10595 
10596 /*@
10597   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10598 
10599   Collective
10600 
10601   Input Parameters:
10602 + A - the matrix
10603 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10604 
10605   Level: advanced
10606 
10607   Note:
10608   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10609 
10610 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10611 @*/
10612 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10613 {
10614   const PetscScalar *vals;
10615   PetscInt          *dnnz;
10616   PetscInt           m, rstart, rend, bs, i, j;
10617 
10618   PetscFunctionBegin;
10619   PetscCall(MatInvertBlockDiagonal(A, &vals));
10620   PetscCall(MatGetBlockSize(A, &bs));
10621   PetscCall(MatGetLocalSize(A, &m, NULL));
10622   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10623   PetscCall(PetscMalloc1(m / bs, &dnnz));
10624   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10625   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10626   PetscCall(PetscFree(dnnz));
10627   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10628   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10629   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10630   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10631   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10632   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10633   PetscFunctionReturn(PETSC_SUCCESS);
10634 }
10635 
10636 /*@C
10637     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10638     via `MatTransposeColoringCreate()`.
10639 
10640     Collective
10641 
10642     Input Parameter:
10643 .   c - coloring context
10644 
10645     Level: intermediate
10646 
10647 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10648 @*/
10649 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10650 {
10651   MatTransposeColoring matcolor = *c;
10652 
10653   PetscFunctionBegin;
10654   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10655   if (--((PetscObject)matcolor)->refct > 0) {
10656     matcolor = NULL;
10657     PetscFunctionReturn(PETSC_SUCCESS);
10658   }
10659 
10660   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10661   PetscCall(PetscFree(matcolor->rows));
10662   PetscCall(PetscFree(matcolor->den2sp));
10663   PetscCall(PetscFree(matcolor->colorforcol));
10664   PetscCall(PetscFree(matcolor->columns));
10665   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10666   PetscCall(PetscHeaderDestroy(c));
10667   PetscFunctionReturn(PETSC_SUCCESS);
10668 }
10669 
10670 /*@C
10671     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10672     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10673     `MatTransposeColoring` to sparse B.
10674 
10675     Collective
10676 
10677     Input Parameters:
10678 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10679 -   B - sparse matrix
10680 
10681     Output Parameter:
10682 .   Btdense - dense matrix B^T
10683 
10684     Level: developer
10685 
10686     Note:
10687     These are used internally for some implementations of `MatRARt()`
10688 
10689 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10690 @*/
10691 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10692 {
10693   PetscFunctionBegin;
10694   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10695   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10696   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10697 
10698   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10699   PetscFunctionReturn(PETSC_SUCCESS);
10700 }
10701 
10702 /*@C
10703     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10704     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10705     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10706     `Csp` from `Cden`.
10707 
10708     Collective
10709 
10710     Input Parameters:
10711 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10712 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10713 
10714     Output Parameter:
10715 .   Csp - sparse matrix
10716 
10717     Level: developer
10718 
10719     Note:
10720     These are used internally for some implementations of `MatRARt()`
10721 
10722 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10723 @*/
10724 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10725 {
10726   PetscFunctionBegin;
10727   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10728   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10729   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10730 
10731   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10732   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10733   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10734   PetscFunctionReturn(PETSC_SUCCESS);
10735 }
10736 
10737 /*@C
10738    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10739 
10740    Collective
10741 
10742    Input Parameters:
10743 +  mat - the matrix product C
10744 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10745 
10746     Output Parameter:
10747 .   color - the new coloring context
10748 
10749     Level: intermediate
10750 
10751 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10752           `MatTransColoringApplyDenToSp()`
10753 @*/
10754 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10755 {
10756   MatTransposeColoring c;
10757   MPI_Comm             comm;
10758 
10759   PetscFunctionBegin;
10760   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10761   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10762   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10763 
10764   c->ctype = iscoloring->ctype;
10765   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10766 
10767   *color = c;
10768   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10769   PetscFunctionReturn(PETSC_SUCCESS);
10770 }
10771 
10772 /*@
10773       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10774         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10775         same, otherwise it will be larger
10776 
10777      Not Collective
10778 
10779   Input Parameter:
10780 .    A  - the matrix
10781 
10782   Output Parameter:
10783 .    state - the current state
10784 
10785   Level: intermediate
10786 
10787   Notes:
10788     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10789          different matrices
10790 
10791     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10792 
10793     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10794 
10795 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10796 @*/
10797 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10798 {
10799   PetscFunctionBegin;
10800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10801   *state = mat->nonzerostate;
10802   PetscFunctionReturn(PETSC_SUCCESS);
10803 }
10804 
10805 /*@
10806       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10807                  matrices from each processor
10808 
10809     Collective
10810 
10811    Input Parameters:
10812 +    comm - the communicators the parallel matrix will live on
10813 .    seqmat - the input sequential matrices
10814 .    n - number of local columns (or `PETSC_DECIDE`)
10815 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10816 
10817    Output Parameter:
10818 .    mpimat - the parallel matrix generated
10819 
10820     Level: developer
10821 
10822    Note:
10823     The number of columns of the matrix in EACH processor MUST be the same.
10824 
10825 .seealso: [](chapter_matrices), `Mat`
10826 @*/
10827 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10828 {
10829   PetscMPIInt size;
10830 
10831   PetscFunctionBegin;
10832   PetscCallMPI(MPI_Comm_size(comm, &size));
10833   if (size == 1) {
10834     if (reuse == MAT_INITIAL_MATRIX) {
10835       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10836     } else {
10837       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10838     }
10839     PetscFunctionReturn(PETSC_SUCCESS);
10840   }
10841 
10842   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");
10843 
10844   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10845   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10846   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10847   PetscFunctionReturn(PETSC_SUCCESS);
10848 }
10849 
10850 /*@
10851      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10852 
10853     Collective
10854 
10855    Input Parameters:
10856 +    A   - the matrix to create subdomains from
10857 -    N   - requested number of subdomains
10858 
10859    Output Parameters:
10860 +    n   - number of subdomains resulting on this rank
10861 -    iss - `IS` list with indices of subdomains on this rank
10862 
10863     Level: advanced
10864 
10865     Note:
10866     The number of subdomains must be smaller than the communicator size
10867 
10868 .seealso: [](chapter_matrices), `Mat`, `IS`
10869 @*/
10870 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10871 {
10872   MPI_Comm    comm, subcomm;
10873   PetscMPIInt size, rank, color;
10874   PetscInt    rstart, rend, k;
10875 
10876   PetscFunctionBegin;
10877   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10878   PetscCallMPI(MPI_Comm_size(comm, &size));
10879   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10880   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);
10881   *n    = 1;
10882   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10883   color = rank / k;
10884   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10885   PetscCall(PetscMalloc1(1, iss));
10886   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10887   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10888   PetscCallMPI(MPI_Comm_free(&subcomm));
10889   PetscFunctionReturn(PETSC_SUCCESS);
10890 }
10891 
10892 /*@
10893    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10894 
10895    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10896    If they are not the same, uses `MatMatMatMult()`.
10897 
10898    Once the coarse grid problem is constructed, correct for interpolation operators
10899    that are not of full rank, which can legitimately happen in the case of non-nested
10900    geometric multigrid.
10901 
10902    Input Parameters:
10903 +  restrct - restriction operator
10904 .  dA - fine grid matrix
10905 .  interpolate - interpolation operator
10906 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10907 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10908 
10909    Output Parameter:
10910 .  A - the Galerkin coarse matrix
10911 
10912    Options Database Key:
10913 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10914 
10915    Level: developer
10916 
10917 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10918 @*/
10919 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10920 {
10921   IS  zerorows;
10922   Vec diag;
10923 
10924   PetscFunctionBegin;
10925   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10926   /* Construct the coarse grid matrix */
10927   if (interpolate == restrct) {
10928     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10929   } else {
10930     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10931   }
10932 
10933   /* If the interpolation matrix is not of full rank, A will have zero rows.
10934      This can legitimately happen in the case of non-nested geometric multigrid.
10935      In that event, we set the rows of the matrix to the rows of the identity,
10936      ignoring the equations (as the RHS will also be zero). */
10937 
10938   PetscCall(MatFindZeroRows(*A, &zerorows));
10939 
10940   if (zerorows != NULL) { /* if there are any zero rows */
10941     PetscCall(MatCreateVecs(*A, &diag, NULL));
10942     PetscCall(MatGetDiagonal(*A, diag));
10943     PetscCall(VecISSet(diag, zerorows, 1.0));
10944     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10945     PetscCall(VecDestroy(&diag));
10946     PetscCall(ISDestroy(&zerorows));
10947   }
10948   PetscFunctionReturn(PETSC_SUCCESS);
10949 }
10950 
10951 /*@C
10952     MatSetOperation - Allows user to set a matrix operation for any matrix type
10953 
10954    Logically Collective
10955 
10956     Input Parameters:
10957 +   mat - the matrix
10958 .   op - the name of the operation
10959 -   f - the function that provides the operation
10960 
10961    Level: developer
10962 
10963     Usage:
10964 .vb
10965   extern PetscErrorCode usermult(Mat, Vec, Vec);
10966 
10967   PetscCall(MatCreateXXX(comm, ..., &A));
10968   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10969 .ve
10970 
10971     Notes:
10972     See the file `include/petscmat.h` for a complete list of matrix
10973     operations, which all have the form MATOP_<OPERATION>, where
10974     <OPERATION> is the name (in all capital letters) of the
10975     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10976 
10977     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10978     sequence as the usual matrix interface routines, since they
10979     are intended to be accessed via the usual matrix interface
10980     routines, e.g.,
10981 .vb
10982   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10983 .ve
10984 
10985     In particular each function MUST return `PETSC_SUCCESS` on success and
10986     nonzero on failure.
10987 
10988     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10989 
10990 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10991 @*/
10992 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10993 {
10994   PetscFunctionBegin;
10995   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10996   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10997   (((void (**)(void))mat->ops)[op]) = f;
10998   PetscFunctionReturn(PETSC_SUCCESS);
10999 }
11000 
11001 /*@C
11002     MatGetOperation - Gets a matrix operation for any matrix type.
11003 
11004     Not Collective
11005 
11006     Input Parameters:
11007 +   mat - the matrix
11008 -   op - the name of the operation
11009 
11010     Output Parameter:
11011 .   f - the function that provides the operation
11012 
11013     Level: developer
11014 
11015     Usage:
11016 .vb
11017       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11018       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11019 .ve
11020 
11021     Notes:
11022     See the file include/petscmat.h for a complete list of matrix
11023     operations, which all have the form MATOP_<OPERATION>, where
11024     <OPERATION> is the name (in all capital letters) of the
11025     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11026 
11027     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11028 
11029 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11030 @*/
11031 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11032 {
11033   PetscFunctionBegin;
11034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11035   *f = (((void (**)(void))mat->ops)[op]);
11036   PetscFunctionReturn(PETSC_SUCCESS);
11037 }
11038 
11039 /*@
11040     MatHasOperation - Determines whether the given matrix supports the particular operation.
11041 
11042    Not Collective
11043 
11044    Input Parameters:
11045 +  mat - the matrix
11046 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11047 
11048    Output Parameter:
11049 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11050 
11051    Level: advanced
11052 
11053    Note:
11054    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11055 
11056 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11057 @*/
11058 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11059 {
11060   PetscFunctionBegin;
11061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11062   PetscValidBoolPointer(has, 3);
11063   if (mat->ops->hasoperation) {
11064     PetscUseTypeMethod(mat, hasoperation, op, has);
11065   } else {
11066     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11067     else {
11068       *has = PETSC_FALSE;
11069       if (op == MATOP_CREATE_SUBMATRIX) {
11070         PetscMPIInt size;
11071 
11072         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11073         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11074       }
11075     }
11076   }
11077   PetscFunctionReturn(PETSC_SUCCESS);
11078 }
11079 
11080 /*@
11081     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11082 
11083    Collective
11084 
11085    Input Parameter:
11086 .  mat - the matrix
11087 
11088    Output Parameter:
11089 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11090 
11091    Level: beginner
11092 
11093 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11094 @*/
11095 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11096 {
11097   PetscFunctionBegin;
11098   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11099   PetscValidType(mat, 1);
11100   PetscValidBoolPointer(cong, 2);
11101   if (!mat->rmap || !mat->cmap) {
11102     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11103     PetscFunctionReturn(PETSC_SUCCESS);
11104   }
11105   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11106     PetscCall(PetscLayoutSetUp(mat->rmap));
11107     PetscCall(PetscLayoutSetUp(mat->cmap));
11108     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11109     if (*cong) mat->congruentlayouts = 1;
11110     else mat->congruentlayouts = 0;
11111   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11112   PetscFunctionReturn(PETSC_SUCCESS);
11113 }
11114 
11115 PetscErrorCode MatSetInf(Mat A)
11116 {
11117   PetscFunctionBegin;
11118   PetscUseTypeMethod(A, setinf);
11119   PetscFunctionReturn(PETSC_SUCCESS);
11120 }
11121 
11122 /*@C
11123    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
11124    and possibly removes small values from the graph structure.
11125 
11126    Collective
11127 
11128    Input Parameters:
11129 +  A - the matrix
11130 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11131 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11132 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11133 
11134    Output Parameter:
11135 .  graph - the resulting graph
11136 
11137    Level: advanced
11138 
11139 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11140 @*/
11141 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11142 {
11143   PetscFunctionBegin;
11144   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11145   PetscValidType(A, 1);
11146   PetscValidLogicalCollectiveBool(A, scale, 3);
11147   PetscValidPointer(graph, 5);
11148   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11149   PetscFunctionReturn(PETSC_SUCCESS);
11150 }
11151 
11152 /*@
11153   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11154   meaning the same memory is used for the matrix, and no new memory is allocated.
11155 
11156   Collective
11157 
11158   Input Parameter:
11159 . A - the matrix
11160 
11161   Level: intermediate
11162 
11163   Developer Note:
11164   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11165   of the arrays in the data structure are unneeded.
11166 
11167 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11168 @*/
11169 PetscErrorCode MatEliminateZeros(Mat A)
11170 {
11171   PetscFunctionBegin;
11172   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11173   PetscUseTypeMethod(A, eliminatezeros);
11174   PetscFunctionReturn(PETSC_SUCCESS);
11175 }
11176