xref: /petsc/src/mat/interface/matrix.c (revision d16ceb7590f23315f034853cec344faff90b289e)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameter:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses MatLoad()
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the sequential dense and AIJ
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary,hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto rank 0 and then shipped to its destination rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their PetscObject name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who's interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245 
1246    PETSc automatically does the byte swapping for
1247 machines that store the bytes reversed. Thus if you write your own binary
1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1249 and `PetscBinaryWrite()` to see how this may be done.
1250 
1251    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1252    Each processor's chunk is loaded independently by its owning rank.
1253    Multiple objects, both matrices and vectors, can be stored within the same file.
1254    They are looked up by their PetscObject name.
1255 
1256    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1257    by default the same structure and naming of the AIJ arrays and column count
1258    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1259 $    save example.mat A b -v7.3
1260    can be directly read by this routine (see Reference 1 for details).
1261 
1262    Depending on your MATLAB version, this format might be a default,
1263    otherwise you can set it as default in Preferences.
1264 
1265    Unless -nocompression flag is used to save the file in MATLAB,
1266    PETSc must be configured with ZLIB package.
1267 
1268    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1269 
1270    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1271 
1272    Corresponding `MatView()` is not yet implemented.
1273 
1274    The loaded matrix is actually a transpose of the original one in MATLAB,
1275    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1276    With this format, matrix is automatically transposed by PETSc,
1277    unless the matrix is marked as SPD or symmetric
1278    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1279 
1280    References:
1281 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1282 
1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1284  @*/
1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1286 {
1287   PetscBool flg;
1288 
1289   PetscFunctionBegin;
1290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1291   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1292 
1293   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1294 
1295   flg = PETSC_FALSE;
1296   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1297   if (flg) {
1298     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1300   }
1301   flg = PETSC_FALSE;
1302   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1303   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1304 
1305   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1306   PetscUseTypeMethod(mat, load, viewer);
1307   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1308   PetscFunctionReturn(PETSC_SUCCESS);
1309 }
1310 
1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1312 {
1313   Mat_Redundant *redund = *redundant;
1314 
1315   PetscFunctionBegin;
1316   if (redund) {
1317     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1318       PetscCall(ISDestroy(&redund->isrow));
1319       PetscCall(ISDestroy(&redund->iscol));
1320       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1321     } else {
1322       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1323       PetscCall(PetscFree(redund->sbuf_j));
1324       PetscCall(PetscFree(redund->sbuf_a));
1325       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1326         PetscCall(PetscFree(redund->rbuf_j[i]));
1327         PetscCall(PetscFree(redund->rbuf_a[i]));
1328       }
1329       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1330     }
1331 
1332     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1333     PetscCall(PetscFree(redund));
1334   }
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 /*@C
1339    MatDestroy - Frees space taken by a matrix.
1340 
1341    Collective
1342 
1343    Input Parameter:
1344 .  A - the matrix
1345 
1346    Level: beginner
1347 
1348    Developer Note:
1349    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1350    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1351    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1352    if changes are needed here.
1353 
1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1355 @*/
1356 PetscErrorCode MatDestroy(Mat *A)
1357 {
1358   PetscFunctionBegin;
1359   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1360   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1361   if (--((PetscObject)(*A))->refct > 0) {
1362     *A = NULL;
1363     PetscFunctionReturn(PETSC_SUCCESS);
1364   }
1365 
1366   /* if memory was published with SAWs then destroy it */
1367   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1368   PetscTryTypeMethod((*A), destroy);
1369 
1370   PetscCall(PetscFree((*A)->factorprefix));
1371   PetscCall(PetscFree((*A)->defaultvectype));
1372   PetscCall(PetscFree((*A)->defaultrandtype));
1373   PetscCall(PetscFree((*A)->bsizes));
1374   PetscCall(PetscFree((*A)->solvertype));
1375   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1376   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1377   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1378   PetscCall(MatProductClear(*A));
1379   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1382   PetscCall(MatDestroy(&(*A)->schur));
1383   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1384   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1385   PetscCall(PetscHeaderDestroy(A));
1386   PetscFunctionReturn(PETSC_SUCCESS);
1387 }
1388 
1389 /*@C
1390    MatSetValues - Inserts or adds a block of values into a matrix.
1391    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1392    MUST be called after all calls to `MatSetValues()` have been completed.
1393 
1394    Not Collective
1395 
1396    Input Parameters:
1397 +  mat - the matrix
1398 .  v - a logically two-dimensional array of values
1399 .  m - the number of rows
1400 .  idxm - the global indices of the rows
1401 .  n - the number of columns
1402 .  idxn - the global indices of the columns
1403 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1404 
1405    Level: beginner
1406 
1407    Notes:
1408    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1409 
1410    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1411    options cannot be mixed without intervening calls to the assembly
1412    routines.
1413 
1414    `MatSetValues()` uses 0-based row and column numbers in Fortran
1415    as well as in C.
1416 
1417    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1418    simply ignored. This allows easily inserting element stiffness matrices
1419    with homogeneous Dirchlet boundary conditions that you don't want represented
1420    in the matrix.
1421 
1422    Efficiency Alert:
1423    The routine `MatSetValuesBlocked()` may offer much better efficiency
1424    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1425 
1426    Developer Note:
1427    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1428    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1429 
1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1431           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1432 @*/
1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1434 {
1435   PetscFunctionBeginHot;
1436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1437   PetscValidType(mat, 1);
1438   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1439   PetscValidIntPointer(idxm, 3);
1440   PetscValidIntPointer(idxn, 5);
1441   MatCheckPreallocated(mat, 1);
1442 
1443   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1444   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1445 
1446   if (PetscDefined(USE_DEBUG)) {
1447     PetscInt i, j;
1448 
1449     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1450     for (i = 0; i < m; i++) {
1451       for (j = 0; j < n; j++) {
1452         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1453 #if defined(PETSC_USE_COMPLEX)
1454           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1455 #else
1456           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1457 #endif
1458       }
1459     }
1460     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1461     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1462   }
1463 
1464   if (mat->assembled) {
1465     mat->was_assembled = PETSC_TRUE;
1466     mat->assembled     = PETSC_FALSE;
1467   }
1468   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1469   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1470   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1471   PetscFunctionReturn(PETSC_SUCCESS);
1472 }
1473 
1474 /*@C
1475    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1476    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1477    MUST be called after all calls to `MatSetValues()` have been completed.
1478 
1479    Not Collective
1480 
1481    Input Parameters:
1482 +  mat - the matrix
1483 .  v - a logically two-dimensional array of values
1484 .  ism - the rows to provide
1485 .  isn - the columns to provide
1486 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1487 
1488    Level: beginner
1489 
1490    Notes:
1491    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1492 
1493    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1494    options cannot be mixed without intervening calls to the assembly
1495    routines.
1496 
1497    `MatSetValues()` uses 0-based row and column numbers in Fortran
1498    as well as in C.
1499 
1500    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1501    simply ignored. This allows easily inserting element stiffness matrices
1502    with homogeneous Dirchlet boundary conditions that you don't want represented
1503    in the matrix.
1504 
1505    Efficiency Alert:
1506    The routine `MatSetValuesBlocked()` may offer much better efficiency
1507    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1508 
1509     This is currently not optimized for any particular `ISType`
1510 
1511    Developer Notes:
1512     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1513                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1514 
1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1516           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1517 @*/
1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1519 {
1520   PetscInt        m, n;
1521   const PetscInt *rows, *cols;
1522 
1523   PetscFunctionBeginHot;
1524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1525   PetscCall(ISGetIndices(ism, &rows));
1526   PetscCall(ISGetIndices(isn, &cols));
1527   PetscCall(ISGetLocalSize(ism, &m));
1528   PetscCall(ISGetLocalSize(isn, &n));
1529   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1530   PetscCall(ISRestoreIndices(ism, &rows));
1531   PetscCall(ISRestoreIndices(isn, &cols));
1532   PetscFunctionReturn(PETSC_SUCCESS);
1533 }
1534 
1535 /*@
1536    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1537         values into a matrix
1538 
1539    Not Collective
1540 
1541    Input Parameters:
1542 +  mat - the matrix
1543 .  row - the (block) row to set
1544 -  v - a logically two-dimensional array of values
1545 
1546    Level: intermediate
1547 
1548    Notes:
1549    The values, `v`, are column-oriented (for the block version) and sorted
1550 
1551    All the nonzeros in the row must be provided
1552 
1553    The matrix must have previously had its column indices set, likely by having been assembled.
1554 
1555    The row must belong to this process
1556 
1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1558           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1559 @*/
1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1561 {
1562   PetscInt globalrow;
1563 
1564   PetscFunctionBegin;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   PetscValidScalarPointer(v, 3);
1568   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1569   PetscCall(MatSetValuesRow(mat, globalrow, v));
1570   PetscFunctionReturn(PETSC_SUCCESS);
1571 }
1572 
1573 /*@
1574    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1575         values into a matrix
1576 
1577    Not Collective
1578 
1579    Input Parameters:
1580 +  mat - the matrix
1581 .  row - the (block) row to set
1582 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1583 
1584    Level: advanced
1585 
1586    Notes:
1587    The values, `v`, are column-oriented for the block version.
1588 
1589    All the nonzeros in the row must be provided
1590 
1591    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1592 
1593    The row must belong to this process
1594 
1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1596           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1597 @*/
1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1599 {
1600   PetscFunctionBeginHot;
1601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1602   PetscValidType(mat, 1);
1603   MatCheckPreallocated(mat, 1);
1604   PetscValidScalarPointer(v, 3);
1605   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1606   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1607   mat->insertmode = INSERT_VALUES;
1608 
1609   if (mat->assembled) {
1610     mat->was_assembled = PETSC_TRUE;
1611     mat->assembled     = PETSC_FALSE;
1612   }
1613   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1614   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1615   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1616   PetscFunctionReturn(PETSC_SUCCESS);
1617 }
1618 
1619 /*@
1620    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1621      Using structured grid indexing
1622 
1623    Not Collective
1624 
1625    Input Parameters:
1626 +  mat - the matrix
1627 .  m - number of rows being entered
1628 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1629 .  n - number of columns being entered
1630 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1631 .  v - a logically two-dimensional array of values
1632 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1633 
1634    Level: beginner
1635 
1636    Notes:
1637    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1638 
1639    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1640    options cannot be mixed without intervening calls to the assembly
1641    routines.
1642 
1643    The grid coordinates are across the entire grid, not just the local portion
1644 
1645    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1646    as well as in C.
1647 
1648    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1649 
1650    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1651    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1652 
1653    The columns and rows in the stencil passed in MUST be contained within the
1654    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1655    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1656    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1657    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1658 
1659    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1660    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1661    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1662    `DM_BOUNDARY_PERIODIC` boundary type.
1663 
1664    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1665    a single value per point) you can skip filling those indices.
1666 
1667    Inspired by the structured grid interface to the HYPRE package
1668    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1669 
1670    Efficiency Alert:
1671    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1672    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1673 
1674    Fortran Note:
1675    `idxm` and `idxn` should be declared as
1676 $     MatStencil idxm(4,m),idxn(4,n)
1677    and the values inserted using
1678 .vb
1679     idxm(MatStencil_i,1) = i
1680     idxm(MatStencil_j,1) = j
1681     idxm(MatStencil_k,1) = k
1682     idxm(MatStencil_c,1) = c
1683     etc
1684 .ve
1685 
1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1687           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1688 @*/
1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1690 {
1691   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1692   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1693   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1694 
1695   PetscFunctionBegin;
1696   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1698   PetscValidType(mat, 1);
1699   PetscValidPointer(idxm, 3);
1700   PetscValidPointer(idxn, 5);
1701 
1702   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1703     jdxm = buf;
1704     jdxn = buf + m;
1705   } else {
1706     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1707     jdxm = bufm;
1708     jdxn = bufn;
1709   }
1710   for (i = 0; i < m; i++) {
1711     for (j = 0; j < 3 - sdim; j++) dxm++;
1712     tmp = *dxm++ - starts[0];
1713     for (j = 0; j < dim - 1; j++) {
1714       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1715       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1716     }
1717     if (mat->stencil.noc) dxm++;
1718     jdxm[i] = tmp;
1719   }
1720   for (i = 0; i < n; i++) {
1721     for (j = 0; j < 3 - sdim; j++) dxn++;
1722     tmp = *dxn++ - starts[0];
1723     for (j = 0; j < dim - 1; j++) {
1724       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1725       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1726     }
1727     if (mat->stencil.noc) dxn++;
1728     jdxn[i] = tmp;
1729   }
1730   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1731   PetscCall(PetscFree2(bufm, bufn));
1732   PetscFunctionReturn(PETSC_SUCCESS);
1733 }
1734 
1735 /*@
1736    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1737      Using structured grid indexing
1738 
1739    Not Collective
1740 
1741    Input Parameters:
1742 +  mat - the matrix
1743 .  m - number of rows being entered
1744 .  idxm - grid coordinates for matrix rows being entered
1745 .  n - number of columns being entered
1746 .  idxn - grid coordinates for matrix columns being entered
1747 .  v - a logically two-dimensional array of values
1748 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1749 
1750    Level: beginner
1751 
1752    Notes:
1753    By default the values, `v`, are row-oriented and unsorted.
1754    See `MatSetOption()` for other options.
1755 
1756    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1757    options cannot be mixed without intervening calls to the assembly
1758    routines.
1759 
1760    The grid coordinates are across the entire grid, not just the local portion
1761 
1762    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1763    as well as in C.
1764 
1765    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1766 
1767    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1768    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1769 
1770    The columns and rows in the stencil passed in MUST be contained within the
1771    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1772    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1773    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1774    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1775 
1776    Negative indices may be passed in idxm and idxn, these rows and columns are
1777    simply ignored. This allows easily inserting element stiffness matrices
1778    with homogeneous Dirchlet boundary conditions that you don't want represented
1779    in the matrix.
1780 
1781    Inspired by the structured grid interface to the HYPRE package
1782    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1783 
1784    Fortran Note:
1785    `idxm` and `idxn` should be declared as
1786 $     MatStencil idxm(4,m),idxn(4,n)
1787    and the values inserted using
1788 .vb
1789     idxm(MatStencil_i,1) = i
1790     idxm(MatStencil_j,1) = j
1791     idxm(MatStencil_k,1) = k
1792    etc
1793 .ve
1794 
1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1796           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1797           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1798 @*/
1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscValidPointer(idxm, 3);
1810   PetscValidPointer(idxn, 5);
1811   PetscValidScalarPointer(v, 6);
1812 
1813   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1814     jdxm = buf;
1815     jdxn = buf + m;
1816   } else {
1817     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1818     jdxm = bufm;
1819     jdxn = bufn;
1820   }
1821   for (i = 0; i < m; i++) {
1822     for (j = 0; j < 3 - sdim; j++) dxm++;
1823     tmp = *dxm++ - starts[0];
1824     for (j = 0; j < sdim - 1; j++) {
1825       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1826       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1827     }
1828     dxm++;
1829     jdxm[i] = tmp;
1830   }
1831   for (i = 0; i < n; i++) {
1832     for (j = 0; j < 3 - sdim; j++) dxn++;
1833     tmp = *dxn++ - starts[0];
1834     for (j = 0; j < sdim - 1; j++) {
1835       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1836       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1837     }
1838     dxn++;
1839     jdxn[i] = tmp;
1840   }
1841   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1842   PetscCall(PetscFree2(bufm, bufn));
1843   PetscFunctionReturn(PETSC_SUCCESS);
1844 }
1845 
1846 /*@
1847    MatSetStencil - Sets the grid information for setting values into a matrix via
1848         `MatSetValuesStencil()`
1849 
1850    Not Collective
1851 
1852    Input Parameters:
1853 +  mat - the matrix
1854 .  dim - dimension of the grid 1, 2, or 3
1855 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1856 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1857 -  dof - number of degrees of freedom per node
1858 
1859    Level: beginner
1860 
1861    Notes:
1862    Inspired by the structured grid interface to the HYPRE package
1863    (www.llnl.gov/CASC/hyper)
1864 
1865    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1866    user.
1867 
1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1869           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1870 @*/
1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1872 {
1873   PetscFunctionBegin;
1874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1875   PetscValidIntPointer(dims, 3);
1876   PetscValidIntPointer(starts, 4);
1877 
1878   mat->stencil.dim = dim + (dof > 1);
1879   for (PetscInt i = 0; i < dim; i++) {
1880     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1881     mat->stencil.starts[i] = starts[dim - i - 1];
1882   }
1883   mat->stencil.dims[dim]   = dof;
1884   mat->stencil.starts[dim] = 0;
1885   mat->stencil.noc         = (PetscBool)(dof == 1);
1886   PetscFunctionReturn(PETSC_SUCCESS);
1887 }
1888 
1889 /*@C
1890    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1891 
1892    Not Collective
1893 
1894    Input Parameters:
1895 +  mat - the matrix
1896 .  v - a logically two-dimensional array of values
1897 .  m  - the number of block rows
1898 .  idxm - the global block indices
1899 .  n - the number of block columns
1900 .  idxn - the global block indices
1901 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1902 
1903    Level: intermediate
1904 
1905    Notes:
1906    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1907    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1908 
1909    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1910    NOT the total number of rows/columns; for example, if the block size is 2 and
1911    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1912    The values in idxm would be 1 2; that is the first index for each block divided by
1913    the block size.
1914 
1915    You must call `MatSetBlockSize()` when constructing this matrix (before
1916    preallocating it).
1917 
1918    By default the values, `v`, are row-oriented, so the layout of
1919    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1920 
1921    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1922    options cannot be mixed without intervening calls to the assembly
1923    routines.
1924 
1925    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1926    as well as in C.
1927 
1928    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1929    simply ignored. This allows easily inserting element stiffness matrices
1930    with homogeneous Dirchlet boundary conditions that you don't want represented
1931    in the matrix.
1932 
1933    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1934    internal searching must be done to determine where to place the
1935    data in the matrix storage space.  By instead inserting blocks of
1936    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1937    reduced.
1938 
1939    Example:
1940 .vb
1941    Suppose m=n=2 and block size(bs) = 2 The array is
1942 
1943    1  2  | 3  4
1944    5  6  | 7  8
1945    - - - | - - -
1946    9  10 | 11 12
1947    13 14 | 15 16
1948 
1949    v[] should be passed in like
1950    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1951 
1952   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1953    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1954 .ve
1955 
1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1957 @*/
1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1959 {
1960   PetscFunctionBeginHot;
1961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1962   PetscValidType(mat, 1);
1963   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1964   PetscValidIntPointer(idxm, 3);
1965   PetscValidIntPointer(idxn, 5);
1966   MatCheckPreallocated(mat, 1);
1967   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1968   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1969   if (PetscDefined(USE_DEBUG)) {
1970     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1971     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1972   }
1973   if (PetscDefined(USE_DEBUG)) {
1974     PetscInt rbs, cbs, M, N, i;
1975     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1976     PetscCall(MatGetSize(mat, &M, &N));
1977     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1978     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1979   }
1980   if (mat->assembled) {
1981     mat->was_assembled = PETSC_TRUE;
1982     mat->assembled     = PETSC_FALSE;
1983   }
1984   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1985   if (mat->ops->setvaluesblocked) {
1986     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1987   } else {
1988     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1989     PetscInt i, j, bs, cbs;
1990 
1991     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1992     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1993       iidxm = buf;
1994       iidxn = buf + m * bs;
1995     } else {
1996       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1997       iidxm = bufr;
1998       iidxn = bufc;
1999     }
2000     for (i = 0; i < m; i++) {
2001       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2002     }
2003     if (m != n || bs != cbs || idxm != idxn) {
2004       for (i = 0; i < n; i++) {
2005         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2006       }
2007     } else iidxn = iidxm;
2008     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2009     PetscCall(PetscFree2(bufr, bufc));
2010   }
2011   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2012   PetscFunctionReturn(PETSC_SUCCESS);
2013 }
2014 
2015 /*@C
2016    MatGetValues - Gets a block of local values from a matrix.
2017 
2018    Not Collective; can only return values that are owned by the give process
2019 
2020    Input Parameters:
2021 +  mat - the matrix
2022 .  v - a logically two-dimensional array for storing the values
2023 .  m  - the number of rows
2024 .  idxm - the  global indices of the rows
2025 .  n - the number of columns
2026 -  idxn - the global indices of the columns
2027 
2028    Level: advanced
2029 
2030    Notes:
2031      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2032      The values, `v`, are then returned in a row-oriented format,
2033      analogous to that used by default in `MatSetValues()`.
2034 
2035      `MatGetValues()` uses 0-based row and column numbers in
2036      Fortran as well as in C.
2037 
2038      `MatGetValues()` requires that the matrix has been assembled
2039      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2040      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2041      without intermediate matrix assembly.
2042 
2043      Negative row or column indices will be ignored and those locations in `v` will be
2044      left unchanged.
2045 
2046      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2047      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2048      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2049 
2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2051 @*/
2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2053 {
2054   PetscFunctionBegin;
2055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2056   PetscValidType(mat, 1);
2057   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2058   PetscValidIntPointer(idxm, 3);
2059   PetscValidIntPointer(idxn, 5);
2060   PetscValidScalarPointer(v, 6);
2061   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2063   MatCheckPreallocated(mat, 1);
2064 
2065   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2066   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2067   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2068   PetscFunctionReturn(PETSC_SUCCESS);
2069 }
2070 
2071 /*@C
2072    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2073      defined previously by `MatSetLocalToGlobalMapping()`
2074 
2075    Not Collective
2076 
2077    Input Parameters:
2078 +  mat - the matrix
2079 .  nrow - number of rows
2080 .  irow - the row local indices
2081 .  ncol - number of columns
2082 -  icol - the column local indices
2083 
2084    Output Parameter:
2085 .  y -  a logically two-dimensional array of values
2086 
2087    Level: advanced
2088 
2089    Notes:
2090      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2091 
2092      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2093      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2094      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2095      with `MatSetLocalToGlobalMapping()`.
2096 
2097    Developer Note:
2098       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2099       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2100 
2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2102           `MatSetValuesLocal()`, `MatGetValues()`
2103 @*/
2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2105 {
2106   PetscFunctionBeginHot;
2107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2108   PetscValidType(mat, 1);
2109   MatCheckPreallocated(mat, 1);
2110   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2111   PetscValidIntPointer(irow, 3);
2112   PetscValidIntPointer(icol, 5);
2113   if (PetscDefined(USE_DEBUG)) {
2114     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2116   }
2117   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2118   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2119   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2120   else {
2121     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2122     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2123       irowm = buf;
2124       icolm = buf + nrow;
2125     } else {
2126       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2127       irowm = bufr;
2128       icolm = bufc;
2129     }
2130     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2131     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2133     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2134     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2135     PetscCall(PetscFree2(bufr, bufc));
2136   }
2137   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2138   PetscFunctionReturn(PETSC_SUCCESS);
2139 }
2140 
2141 /*@
2142   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2143   the same size. Currently, this can only be called once and creates the given matrix.
2144 
2145   Not Collective
2146 
2147   Input Parameters:
2148 + mat - the matrix
2149 . nb - the number of blocks
2150 . bs - the number of rows (and columns) in each block
2151 . rows - a concatenation of the rows for each block
2152 - v - a concatenation of logically two-dimensional arrays of values
2153 
2154   Level: advanced
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2162           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2163 @*/
2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2165 {
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2168   PetscValidType(mat, 1);
2169   PetscValidIntPointer(rows, 4);
2170   PetscValidScalarPointer(v, 5);
2171   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2172 
2173   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2174   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2175   else {
2176     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2177   }
2178   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2179   PetscFunctionReturn(PETSC_SUCCESS);
2180 }
2181 
2182 /*@
2183    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2184    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2185    using a local (per-processor) numbering.
2186 
2187    Not Collective
2188 
2189    Input Parameters:
2190 +  x - the matrix
2191 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2192 -  cmapping - column mapping
2193 
2194    Level: intermediate
2195 
2196    Note:
2197    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2198 
2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2200 @*/
2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2202 {
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2205   PetscValidType(x, 1);
2206   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2207   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2208   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2209   else {
2210     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2212   }
2213   PetscFunctionReturn(PETSC_SUCCESS);
2214 }
2215 
2216 /*@
2217    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2218 
2219    Not Collective
2220 
2221    Input Parameter:
2222 .  A - the matrix
2223 
2224    Output Parameters:
2225 + rmapping - row mapping
2226 - cmapping - column mapping
2227 
2228    Level: advanced
2229 
2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2236   PetscValidType(A, 1);
2237   if (rmapping) {
2238     PetscValidPointer(rmapping, 2);
2239     *rmapping = A->rmap->mapping;
2240   }
2241   if (cmapping) {
2242     PetscValidPointer(cmapping, 3);
2243     *cmapping = A->cmap->mapping;
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2250 
2251    Logically Collective
2252 
2253    Input Parameters:
2254 +  A - the matrix
2255 . rmap - row layout
2256 - cmap - column layout
2257 
2258    Level: advanced
2259 
2260    Note:
2261    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2262 
2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2264 @*/
2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2269   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2270   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2271   PetscFunctionReturn(PETSC_SUCCESS);
2272 }
2273 
2274 /*@
2275    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2276 
2277    Not Collective
2278 
2279    Input Parameter:
2280 .  A - the matrix
2281 
2282    Output Parameters:
2283 + rmap - row layout
2284 - cmap - column layout
2285 
2286    Level: advanced
2287 
2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2289 @*/
2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2291 {
2292   PetscFunctionBegin;
2293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2294   PetscValidType(A, 1);
2295   if (rmap) {
2296     PetscValidPointer(rmap, 2);
2297     *rmap = A->rmap;
2298   }
2299   if (cmap) {
2300     PetscValidPointer(cmap, 3);
2301     *cmap = A->cmap;
2302   }
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@C
2307    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2308    using a local numbering of the nodes.
2309 
2310    Not Collective
2311 
2312    Input Parameters:
2313 +  mat - the matrix
2314 .  nrow - number of rows
2315 .  irow - the row local indices
2316 .  ncol - number of columns
2317 .  icol - the column local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Level: intermediate
2322 
2323    Notes:
2324    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2325       `MatSetUp()` before using this routine
2326 
2327    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2328 
2329    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2330    options cannot be mixed without intervening calls to the assembly
2331    routines.
2332 
2333    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2334    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow - number of rows
2402 .  irow - the row local indices
2403 .  ncol - number of columns
2404 .  icol - the column local indices
2405 .  y -  a logically two-dimensional array of values
2406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2407 
2408    Level: intermediate
2409 
2410    Notes:
2411    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2412       `MatSetUp()` before using this routine
2413 
2414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2415       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2416 
2417    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2418    options cannot be mixed without intervening calls to the assembly
2419    routines.
2420 
2421    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2422    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2423 
2424    Developer Note:
2425     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2426                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2427 
2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2429           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2430 @*/
2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2432 {
2433   PetscFunctionBeginHot;
2434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2435   PetscValidType(mat, 1);
2436   MatCheckPreallocated(mat, 1);
2437   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2438   PetscValidIntPointer(irow, 3);
2439   PetscValidIntPointer(icol, 5);
2440   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2441   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2442   if (PetscDefined(USE_DEBUG)) {
2443     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2444     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2445   }
2446 
2447   if (mat->assembled) {
2448     mat->was_assembled = PETSC_TRUE;
2449     mat->assembled     = PETSC_FALSE;
2450   }
2451   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2452     PetscInt irbs, rbs;
2453     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2454     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2455     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2456   }
2457   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2458     PetscInt icbs, cbs;
2459     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2460     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2461     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2462   }
2463   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2464   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2465   else {
2466     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2467     const PetscInt *irowm, *icolm;
2468 
2469     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2470       bufr  = buf;
2471       bufc  = buf + nrow;
2472       irowm = bufr;
2473       icolm = bufc;
2474     } else {
2475       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2476       irowm = bufr;
2477       icolm = bufc;
2478     }
2479     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2480     else irowm = irow;
2481     if (mat->cmap->mapping) {
2482       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2483         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2484       } else icolm = irowm;
2485     } else icolm = icol;
2486     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2487     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2488   }
2489   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2490   PetscFunctionReturn(PETSC_SUCCESS);
2491 }
2492 
2493 /*@
2494    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2495 
2496    Collective
2497 
2498    Input Parameters:
2499 +  mat - the matrix
2500 -  x   - the vector to be multiplied
2501 
2502    Output Parameter:
2503 .  y - the result
2504 
2505    Level: developer
2506 
2507    Note:
2508    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2509    call `MatMultDiagonalBlock`(A,y,y).
2510 
2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2512 @*/
2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2514 {
2515   PetscFunctionBegin;
2516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2517   PetscValidType(mat, 1);
2518   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2519   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2520 
2521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2523   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2524   MatCheckPreallocated(mat, 1);
2525 
2526   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2527   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2528   PetscFunctionReturn(PETSC_SUCCESS);
2529 }
2530 
2531 /*@
2532    MatMult - Computes the matrix-vector product, y = Ax.
2533 
2534    Neighbor-wise Collective
2535 
2536    Input Parameters:
2537 +  mat - the matrix
2538 -  x   - the vector to be multiplied
2539 
2540    Output Parameter:
2541 .  y - the result
2542 
2543    Level: beginner
2544 
2545    Note:
2546    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2547    call `MatMult`(A,y,y).
2548 
2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2550 @*/
2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2552 {
2553   PetscFunctionBegin;
2554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2555   PetscValidType(mat, 1);
2556   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2557   VecCheckAssembled(x);
2558   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2561   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2562   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2563   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2564   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2565   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2566   PetscCall(VecSetErrorIfLocked(y, 3));
2567   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2568   MatCheckPreallocated(mat, 1);
2569 
2570   PetscCall(VecLockReadPush(x));
2571   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2572   PetscUseTypeMethod(mat, mult, x, y);
2573   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2574   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2575   PetscCall(VecLockReadPop(x));
2576   PetscFunctionReturn(PETSC_SUCCESS);
2577 }
2578 
2579 /*@
2580    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2581 
2582    Neighbor-wise Collective
2583 
2584    Input Parameters:
2585 +  mat - the matrix
2586 -  x   - the vector to be multiplied
2587 
2588    Output Parameter:
2589 .  y - the result
2590 
2591    Level: beginner
2592 
2593    Notes:
2594    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2595    call `MatMultTranspose`(A,y,y).
2596 
2597    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2598    use `MatMultHermitianTranspose()`
2599 
2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2601 @*/
2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2603 {
2604   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2605 
2606   PetscFunctionBegin;
2607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2608   PetscValidType(mat, 1);
2609   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2610   VecCheckAssembled(x);
2611   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2612 
2613   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2614   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2615   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2616   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2617   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2618   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2619   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2620   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2621   MatCheckPreallocated(mat, 1);
2622 
2623   if (!mat->ops->multtranspose) {
2624     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2625     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2626   } else op = mat->ops->multtranspose;
2627   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2628   PetscCall(VecLockReadPush(x));
2629   PetscCall((*op)(mat, x, y));
2630   PetscCall(VecLockReadPop(x));
2631   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2632   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2633   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2634   PetscFunctionReturn(PETSC_SUCCESS);
2635 }
2636 
2637 /*@
2638    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2639 
2640    Neighbor-wise Collective
2641 
2642    Input Parameters:
2643 +  mat - the matrix
2644 -  x   - the vector to be multilplied
2645 
2646    Output Parameter:
2647 .  y - the result
2648 
2649    Level: beginner
2650 
2651    Notes:
2652    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2653    call `MatMultHermitianTranspose`(A,y,y).
2654 
2655    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2656 
2657    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2658 
2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2660 @*/
2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2662 {
2663   PetscFunctionBegin;
2664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2665   PetscValidType(mat, 1);
2666   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2667   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2668 
2669   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2670   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2671   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2672   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2673   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2674   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2675   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2676   MatCheckPreallocated(mat, 1);
2677 
2678   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2679 #if defined(PETSC_USE_COMPLEX)
2680   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2681     PetscCall(VecLockReadPush(x));
2682     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2683     else PetscUseTypeMethod(mat, mult, x, y);
2684     PetscCall(VecLockReadPop(x));
2685   } else {
2686     Vec w;
2687     PetscCall(VecDuplicate(x, &w));
2688     PetscCall(VecCopy(x, w));
2689     PetscCall(VecConjugate(w));
2690     PetscCall(MatMultTranspose(mat, w, y));
2691     PetscCall(VecDestroy(&w));
2692     PetscCall(VecConjugate(y));
2693   }
2694   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2695 #else
2696   PetscCall(MatMultTranspose(mat, x, y));
2697 #endif
2698   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2699   PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701 
2702 /*@
2703     MatMultAdd -  Computes v3 = v2 + A * v1.
2704 
2705     Neighbor-wise Collective
2706 
2707     Input Parameters:
2708 +   mat - the matrix
2709 .   v1 - the vector to be multiplied by `mat`
2710 -   v2 - the vector to be added to the result
2711 
2712     Output Parameter:
2713 .   v3 - the result
2714 
2715     Level: beginner
2716 
2717     Note:
2718     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2719     call `MatMultAdd`(A,v1,v2,v1).
2720 
2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2722 @*/
2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2724 {
2725   PetscFunctionBegin;
2726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2727   PetscValidType(mat, 1);
2728   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2729   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2730   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2731 
2732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2734   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2735   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2736      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2737   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2738   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2739   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2740   MatCheckPreallocated(mat, 1);
2741 
2742   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2743   PetscCall(VecLockReadPush(v1));
2744   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2745   PetscCall(VecLockReadPop(v1));
2746   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2747   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2748   PetscFunctionReturn(PETSC_SUCCESS);
2749 }
2750 
2751 /*@
2752    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2753 
2754    Neighbor-wise Collective
2755 
2756    Input Parameters:
2757 +  mat - the matrix
2758 .  v1 - the vector to be multiplied by the transpose of the matrix
2759 -  v2 - the vector to be added to the result
2760 
2761    Output Parameter:
2762 .  v3 - the result
2763 
2764    Level: beginner
2765 
2766    Note:
2767    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2768    call `MatMultTransposeAdd`(A,v1,v2,v1).
2769 
2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2771 @*/
2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2773 {
2774   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2775 
2776   PetscFunctionBegin;
2777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2778   PetscValidType(mat, 1);
2779   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2780   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2781   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2782 
2783   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2784   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2785   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2786   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2787   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2788   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2789   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2790   MatCheckPreallocated(mat, 1);
2791 
2792   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2793   PetscCall(VecLockReadPush(v1));
2794   PetscCall((*op)(mat, v1, v2, v3));
2795   PetscCall(VecLockReadPop(v1));
2796   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2797   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2798   PetscFunctionReturn(PETSC_SUCCESS);
2799 }
2800 
2801 /*@
2802    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2803 
2804    Neighbor-wise Collective
2805 
2806    Input Parameters:
2807 +  mat - the matrix
2808 .  v1 - the vector to be multiplied by the Hermitian transpose
2809 -  v2 - the vector to be added to the result
2810 
2811    Output Parameter:
2812 .  v3 - the result
2813 
2814    Level: beginner
2815 
2816    Note:
2817    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2818    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2819 
2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2821 @*/
2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2823 {
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2826   PetscValidType(mat, 1);
2827   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2828   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2829   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2830 
2831   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2832   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2833   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2834   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2835   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2836   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2837   MatCheckPreallocated(mat, 1);
2838 
2839   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2840   PetscCall(VecLockReadPush(v1));
2841   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2842   else {
2843     Vec w, z;
2844     PetscCall(VecDuplicate(v1, &w));
2845     PetscCall(VecCopy(v1, w));
2846     PetscCall(VecConjugate(w));
2847     PetscCall(VecDuplicate(v3, &z));
2848     PetscCall(MatMultTranspose(mat, w, z));
2849     PetscCall(VecDestroy(&w));
2850     PetscCall(VecConjugate(z));
2851     if (v2 != v3) {
2852       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2853     } else {
2854       PetscCall(VecAXPY(v3, 1.0, z));
2855     }
2856     PetscCall(VecDestroy(&z));
2857   }
2858   PetscCall(VecLockReadPop(v1));
2859   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2860   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2861   PetscFunctionReturn(PETSC_SUCCESS);
2862 }
2863 
2864 /*@C
2865    MatGetFactorType - gets the type of factorization it is
2866 
2867    Not Collective
2868 
2869    Input Parameter:
2870 .  mat - the matrix
2871 
2872    Output Parameter:
2873 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2874 
2875    Level: intermediate
2876 
2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2878           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2879 @*/
2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2881 {
2882   PetscFunctionBegin;
2883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2884   PetscValidType(mat, 1);
2885   PetscValidPointer(t, 2);
2886   *t = mat->factortype;
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891    MatSetFactorType - sets the type of factorization it is
2892 
2893    Logically Collective
2894 
2895    Input Parameters:
2896 +  mat - the matrix
2897 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2898 
2899    Level: intermediate
2900 
2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   mat->factortype = t;
2910   PetscFunctionReturn(PETSC_SUCCESS);
2911 }
2912 
2913 /*@C
2914    MatGetInfo - Returns information about matrix storage (number of
2915    nonzeros, memory, etc.).
2916 
2917    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2918 
2919    Input Parameters:
2920 +  mat - the matrix
2921 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2922 
2923    Output Parameter:
2924 .  info - matrix information context
2925 
2926    Notes:
2927    The `MatInfo` context contains a variety of matrix data, including
2928    number of nonzeros allocated and used, number of mallocs during
2929    matrix assembly, etc.  Additional information for factored matrices
2930    is provided (such as the fill ratio, number of mallocs during
2931    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2932    when using the runtime options
2933 $       -info -mat_view ::ascii_info
2934 
2935    Example:
2936    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2937    data within the MatInfo context.  For example,
2938 .vb
2939       MatInfo info;
2940       Mat     A;
2941       double  mal, nz_a, nz_u;
2942 
2943       MatGetInfo(A,MAT_LOCAL,&info);
2944       mal  = info.mallocs;
2945       nz_a = info.nz_allocated;
2946 .ve
2947 
2948    Fortran users should declare info as a double precision
2949    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2950    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2951    a complete list of parameter names.
2952 .vb
2953       double  precision info(MAT_INFO_SIZE)
2954       double  precision mal, nz_a
2955       Mat     A
2956       integer ierr
2957 
2958       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2959       mal = info(MAT_INFO_MALLOCS)
2960       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2961 .ve
2962 
2963     Level: intermediate
2964 
2965     Developer Note:
2966     The Fortran interface is not autogenerated as the
2967     interface definition cannot be generated correctly [due to `MatInfo` argument]
2968 
2969 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2970 @*/
2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2972 {
2973   PetscFunctionBegin;
2974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2975   PetscValidType(mat, 1);
2976   PetscValidPointer(info, 3);
2977   MatCheckPreallocated(mat, 1);
2978   PetscUseTypeMethod(mat, getinfo, flag, info);
2979   PetscFunctionReturn(PETSC_SUCCESS);
2980 }
2981 
2982 /*
2983    This is used by external packages where it is not easy to get the info from the actual
2984    matrix factorization.
2985 */
2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2987 {
2988   PetscFunctionBegin;
2989   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2990   PetscFunctionReturn(PETSC_SUCCESS);
2991 }
2992 
2993 /*@C
2994    MatLUFactor - Performs in-place LU factorization of matrix.
2995 
2996    Collective
2997 
2998    Input Parameters:
2999 +  mat - the matrix
3000 .  row - row permutation
3001 .  col - column permutation
3002 -  info - options for factorization, includes
3003 .vb
3004           fill - expected fill as ratio of original fill.
3005           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3006                    Run with the option -info to determine an optimal value to use
3007 .ve
3008    Level: developer
3009 
3010    Notes:
3011    Most users should employ the `KSP` interface for linear solvers
3012    instead of working directly with matrix algebra routines such as this.
3013    See, e.g., `KSPCreate()`.
3014 
3015    This changes the state of the matrix to a factored matrix; it cannot be used
3016    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3017 
3018    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3019    when not using `KSP`.
3020 
3021    Developer Note:
3022    The Fortran interface is not autogenerated as the
3023    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3024 
3025 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3026           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3027 @*/
3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3029 {
3030   MatFactorInfo tinfo;
3031 
3032   PetscFunctionBegin;
3033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3034   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3035   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3036   if (info) PetscValidPointer(info, 4);
3037   PetscValidType(mat, 1);
3038   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3039   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3040   MatCheckPreallocated(mat, 1);
3041   if (!info) {
3042     PetscCall(MatFactorInfoInitialize(&tinfo));
3043     info = &tinfo;
3044   }
3045 
3046   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3047   PetscUseTypeMethod(mat, lufactor, row, col, info);
3048   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3049   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3050   PetscFunctionReturn(PETSC_SUCCESS);
3051 }
3052 
3053 /*@C
3054    MatILUFactor - Performs in-place ILU factorization of matrix.
3055 
3056    Collective
3057 
3058    Input Parameters:
3059 +  mat - the matrix
3060 .  row - row permutation
3061 .  col - column permutation
3062 -  info - structure containing
3063 .vb
3064       levels - number of levels of fill.
3065       expected fill - as ratio of original fill.
3066       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3067                 missing diagonal entries)
3068 .ve
3069 
3070    Level: developer
3071 
3072    Notes:
3073    Most users should employ the `KSP` interface for linear solvers
3074    instead of working directly with matrix algebra routines such as this.
3075    See, e.g., `KSPCreate()`.
3076 
3077    Probably really in-place only when level of fill is zero, otherwise allocates
3078    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3079    when not using `KSP`.
3080 
3081    Developer Note:
3082    The Fortran interface is not autogenerated as the
3083    interface definition cannot be generated correctly [due to MatFactorInfo]
3084 
3085 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3086 @*/
3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3088 {
3089   PetscFunctionBegin;
3090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3091   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3092   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3093   PetscValidPointer(info, 4);
3094   PetscValidType(mat, 1);
3095   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3096   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3097   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3098   MatCheckPreallocated(mat, 1);
3099 
3100   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3101   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3102   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3103   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3104   PetscFunctionReturn(PETSC_SUCCESS);
3105 }
3106 
3107 /*@C
3108    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3109    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3110 
3111    Collective
3112 
3113    Input Parameters:
3114 +  fact - the factor matrix obtained with `MatGetFactor()`
3115 .  mat - the matrix
3116 .  row - the row permutation
3117 .  col - the column permutation
3118 -  info - options for factorization, includes
3119 .vb
3120           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3121           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3122 .ve
3123 
3124    Level: developer
3125 
3126    Notes:
3127     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3128 
3129    Most users should employ the simplified `KSP` interface for linear solvers
3130    instead of working directly with matrix algebra routines such as this.
3131    See, e.g., `KSPCreate()`.
3132 
3133    Developer Note:
3134    The Fortran interface is not autogenerated as the
3135    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3136 
3137 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3138 @*/
3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3140 {
3141   MatFactorInfo tinfo;
3142 
3143   PetscFunctionBegin;
3144   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
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(fact, 1);
3150   PetscValidType(mat, 2);
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   MatCheckPreallocated(mat, 2);
3154   if (!info) {
3155     PetscCall(MatFactorInfoInitialize(&tinfo));
3156     info = &tinfo;
3157   }
3158 
3159   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3160   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3161   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3162   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3163   PetscFunctionReturn(PETSC_SUCCESS);
3164 }
3165 
3166 /*@C
3167    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3168    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3169 
3170    Collective
3171 
3172    Input Parameters:
3173 +  fact - the factor matrix obtained with `MatGetFactor()`
3174 .  mat - the matrix
3175 -  info - options for factorization
3176 
3177    Level: developer
3178 
3179    Notes:
3180    See `MatLUFactor()` for in-place factorization.  See
3181    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3182 
3183    Most users should employ the `KSP` interface for linear solvers
3184    instead of working directly with matrix algebra routines such as this.
3185    See, e.g., `KSPCreate()`.
3186 
3187     Developer Note:
3188     The Fortran interface is not autogenerated as the
3189     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3190 
3191 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3192 @*/
3193 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3194 {
3195   MatFactorInfo tinfo;
3196 
3197   PetscFunctionBegin;
3198   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3200   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3201   PetscValidType(fact, 1);
3202   PetscValidType(mat, 2);
3203   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3204   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,
3205              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3206 
3207   MatCheckPreallocated(mat, 2);
3208   if (!info) {
3209     PetscCall(MatFactorInfoInitialize(&tinfo));
3210     info = &tinfo;
3211   }
3212 
3213   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3214   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3215   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3216   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3217   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3218   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3219   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3220   PetscFunctionReturn(PETSC_SUCCESS);
3221 }
3222 
3223 /*@C
3224    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3225    symmetric matrix.
3226 
3227    Collective
3228 
3229    Input Parameters:
3230 +  mat - the matrix
3231 .  perm - row and column permutations
3232 -  f - expected fill as ratio of original fill
3233 
3234    Level: developer
3235 
3236    Notes:
3237    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3238    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3239 
3240    Most users should employ the `KSP` interface for linear solvers
3241    instead of working directly with matrix algebra routines such as this.
3242    See, e.g., `KSPCreate()`.
3243 
3244    Developer Note:
3245    The Fortran interface is not autogenerated as the
3246    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3247 
3248 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3249           `MatGetOrdering()`
3250 @*/
3251 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3252 {
3253   MatFactorInfo tinfo;
3254 
3255   PetscFunctionBegin;
3256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3257   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3258   if (info) PetscValidPointer(info, 3);
3259   PetscValidType(mat, 1);
3260   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3263   MatCheckPreallocated(mat, 1);
3264   if (!info) {
3265     PetscCall(MatFactorInfoInitialize(&tinfo));
3266     info = &tinfo;
3267   }
3268 
3269   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3270   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3271   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3272   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3273   PetscFunctionReturn(PETSC_SUCCESS);
3274 }
3275 
3276 /*@C
3277    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3278    of a symmetric matrix.
3279 
3280    Collective
3281 
3282    Input Parameters:
3283 +  fact - the factor matrix obtained with `MatGetFactor()`
3284 .  mat - the matrix
3285 .  perm - row and column permutations
3286 -  info - options for factorization, includes
3287 .vb
3288           fill - expected fill as ratio of original fill.
3289           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3290                    Run with the option -info to determine an optimal value to use
3291 .ve
3292 
3293    Level: developer
3294 
3295    Notes:
3296    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3297    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3298 
3299    Most users should employ the `KSP` interface for linear solvers
3300    instead of working directly with matrix algebra routines such as this.
3301    See, e.g., `KSPCreate()`.
3302 
3303    Developer Note:
3304    The Fortran interface is not autogenerated as the
3305    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3306 
3307 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3308           `MatGetOrdering()`
3309 @*/
3310 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3311 {
3312   MatFactorInfo tinfo;
3313 
3314   PetscFunctionBegin;
3315   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3316   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3317   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3318   if (info) PetscValidPointer(info, 4);
3319   PetscValidType(fact, 1);
3320   PetscValidType(mat, 2);
3321   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3322   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3323   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3324   MatCheckPreallocated(mat, 2);
3325   if (!info) {
3326     PetscCall(MatFactorInfoInitialize(&tinfo));
3327     info = &tinfo;
3328   }
3329 
3330   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3331   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3332   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3333   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3334   PetscFunctionReturn(PETSC_SUCCESS);
3335 }
3336 
3337 /*@C
3338    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3339    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3340    `MatCholeskyFactorSymbolic()`.
3341 
3342    Collective
3343 
3344    Input Parameters:
3345 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3346 .  mat - the initial matrix that is to be factored
3347 -  info - options for factorization
3348 
3349    Level: developer
3350 
3351    Note:
3352    Most users should employ the `KSP` interface for linear solvers
3353    instead of working directly with matrix algebra routines such as this.
3354    See, e.g., `KSPCreate()`.
3355 
3356    Developer Note:
3357    The Fortran interface is not autogenerated as the
3358    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3359 
3360 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3361 @*/
3362 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3363 {
3364   MatFactorInfo tinfo;
3365 
3366   PetscFunctionBegin;
3367   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3369   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3370   PetscValidType(fact, 1);
3371   PetscValidType(mat, 2);
3372   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3373   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,
3374              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3375   MatCheckPreallocated(mat, 2);
3376   if (!info) {
3377     PetscCall(MatFactorInfoInitialize(&tinfo));
3378     info = &tinfo;
3379   }
3380 
3381   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3382   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3383   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3384   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3385   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3386   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3387   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3388   PetscFunctionReturn(PETSC_SUCCESS);
3389 }
3390 
3391 /*@
3392    MatQRFactor - Performs in-place QR factorization of matrix.
3393 
3394    Collective
3395 
3396    Input Parameters:
3397 +  mat - the matrix
3398 .  col - column permutation
3399 -  info - options for factorization, includes
3400 .vb
3401           fill - expected fill as ratio of original fill.
3402           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3403                    Run with the option -info to determine an optimal value to use
3404 .ve
3405 
3406    Level: developer
3407 
3408    Notes:
3409    Most users should employ the `KSP` interface for linear solvers
3410    instead of working directly with matrix algebra routines such as this.
3411    See, e.g., `KSPCreate()`.
3412 
3413    This changes the state of the matrix to a factored matrix; it cannot be used
3414    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3415 
3416    Developer Note:
3417    The Fortran interface is not autogenerated as the
3418    interface definition cannot be generated correctly [due to MatFactorInfo]
3419 
3420 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3421           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3422 @*/
3423 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3424 {
3425   PetscFunctionBegin;
3426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3427   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3428   if (info) PetscValidPointer(info, 3);
3429   PetscValidType(mat, 1);
3430   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3431   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3432   MatCheckPreallocated(mat, 1);
3433   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3434   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3435   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3436   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3437   PetscFunctionReturn(PETSC_SUCCESS);
3438 }
3439 
3440 /*@
3441    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3442    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3443 
3444    Collective
3445 
3446    Input Parameters:
3447 +  fact - the factor matrix obtained with `MatGetFactor()`
3448 .  mat - the matrix
3449 .  col - column permutation
3450 -  info - options for factorization, includes
3451 .vb
3452           fill - expected fill as ratio of original fill.
3453           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3454                    Run with the option -info to determine an optimal value to use
3455 .ve
3456 
3457    Level: developer
3458 
3459    Note:
3460    Most users should employ the `KSP` interface for linear solvers
3461    instead of working directly with matrix algebra routines such as this.
3462    See, e.g., `KSPCreate()`.
3463 
3464    Developer Note:
3465    The Fortran interface is not autogenerated as the
3466    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3467 
3468 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3469 @*/
3470 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3471 {
3472   MatFactorInfo tinfo;
3473 
3474   PetscFunctionBegin;
3475   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3477   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3478   if (info) PetscValidPointer(info, 4);
3479   PetscValidType(fact, 1);
3480   PetscValidType(mat, 2);
3481   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3482   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3483   MatCheckPreallocated(mat, 2);
3484   if (!info) {
3485     PetscCall(MatFactorInfoInitialize(&tinfo));
3486     info = &tinfo;
3487   }
3488 
3489   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3490   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3491   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3492   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3493   PetscFunctionReturn(PETSC_SUCCESS);
3494 }
3495 
3496 /*@
3497    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3498    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3499 
3500    Collective
3501 
3502    Input Parameters:
3503 +  fact - the factor matrix obtained with `MatGetFactor()`
3504 .  mat - the matrix
3505 -  info - options for factorization
3506 
3507    Level: developer
3508 
3509    Notes:
3510    See `MatQRFactor()` for in-place factorization.
3511 
3512    Most users should employ the `KSP` interface for linear solvers
3513    instead of working directly with matrix algebra routines such as this.
3514    See, e.g., `KSPCreate()`.
3515 
3516    Developer Note:
3517    The Fortran interface is not autogenerated as the
3518    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3519 
3520 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3521 @*/
3522 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3523 {
3524   MatFactorInfo tinfo;
3525 
3526   PetscFunctionBegin;
3527   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3529   PetscValidType(fact, 1);
3530   PetscValidType(mat, 2);
3531   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3532   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,
3533              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3534 
3535   MatCheckPreallocated(mat, 2);
3536   if (!info) {
3537     PetscCall(MatFactorInfoInitialize(&tinfo));
3538     info = &tinfo;
3539   }
3540 
3541   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3542   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3543   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3544   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3545   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3546   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3547   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3548   PetscFunctionReturn(PETSC_SUCCESS);
3549 }
3550 
3551 /*@
3552    MatSolve - Solves A x = b, given a factored matrix.
3553 
3554    Neighbor-wise Collective
3555 
3556    Input Parameters:
3557 +  mat - the factored matrix
3558 -  b - the right-hand-side vector
3559 
3560    Output Parameter:
3561 .  x - the result vector
3562 
3563    Level: developer
3564 
3565    Notes:
3566    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3567    call `MatSolve`(A,x,x).
3568 
3569    Most users should employ the `KSP` interface for linear solvers
3570    instead of working directly with matrix algebra routines such as this.
3571    See, e.g., `KSPCreate()`.
3572 
3573 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3574 @*/
3575 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3576 {
3577   PetscFunctionBegin;
3578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3579   PetscValidType(mat, 1);
3580   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3581   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3582   PetscCheckSameComm(mat, 1, b, 2);
3583   PetscCheckSameComm(mat, 1, x, 3);
3584   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3585   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);
3586   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);
3587   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);
3588   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3589   MatCheckPreallocated(mat, 1);
3590 
3591   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3592   if (mat->factorerrortype) {
3593     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3594     PetscCall(VecSetInf(x));
3595   } else PetscUseTypeMethod(mat, solve, b, x);
3596   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3597   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3598   PetscFunctionReturn(PETSC_SUCCESS);
3599 }
3600 
3601 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3602 {
3603   Vec      b, x;
3604   PetscInt N, i;
3605   PetscErrorCode (*f)(Mat, Vec, Vec);
3606   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3607 
3608   PetscFunctionBegin;
3609   if (A->factorerrortype) {
3610     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3611     PetscCall(MatSetInf(X));
3612     PetscFunctionReturn(PETSC_SUCCESS);
3613   }
3614   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3615   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3616   PetscCall(MatBoundToCPU(A, &Abound));
3617   if (!Abound) {
3618     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3619     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3620   }
3621 #if defined(PETSC_HAVE_CUDA)
3622   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3623   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3624 #elif (PETSC_HAVE_HIP)
3625   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3626   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3627 #endif
3628   PetscCall(MatGetSize(B, NULL, &N));
3629   for (i = 0; i < N; i++) {
3630     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3631     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3632     PetscCall((*f)(A, b, x));
3633     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3634     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3635   }
3636   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3637   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3638   PetscFunctionReturn(PETSC_SUCCESS);
3639 }
3640 
3641 /*@
3642    MatMatSolve - Solves A X = B, given a factored matrix.
3643 
3644    Neighbor-wise Collective
3645 
3646    Input Parameters:
3647 +  A - the factored matrix
3648 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3649 
3650    Output Parameter:
3651 .  X - the result matrix (dense matrix)
3652 
3653    Level: developer
3654 
3655    Note:
3656    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3657    otherwise, `B` and `X` cannot be the same.
3658 
3659 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3660 @*/
3661 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3662 {
3663   PetscFunctionBegin;
3664   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3665   PetscValidType(A, 1);
3666   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3667   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3668   PetscCheckSameComm(A, 1, B, 2);
3669   PetscCheckSameComm(A, 1, X, 3);
3670   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);
3671   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);
3672   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");
3673   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3674   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3675   MatCheckPreallocated(A, 1);
3676 
3677   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3678   if (!A->ops->matsolve) {
3679     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3680     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3681   } else PetscUseTypeMethod(A, matsolve, B, X);
3682   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3683   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3684   PetscFunctionReturn(PETSC_SUCCESS);
3685 }
3686 
3687 /*@
3688    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3689 
3690    Neighbor-wise Collective
3691 
3692    Input Parameters:
3693 +  A - the factored matrix
3694 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3695 
3696    Output Parameter:
3697 .  X - the result matrix (dense matrix)
3698 
3699    Level: developer
3700 
3701    Note:
3702    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3703    call `MatMatSolveTranspose`(A,X,X).
3704 
3705 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3706 @*/
3707 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3708 {
3709   PetscFunctionBegin;
3710   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3711   PetscValidType(A, 1);
3712   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3713   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3714   PetscCheckSameComm(A, 1, B, 2);
3715   PetscCheckSameComm(A, 1, X, 3);
3716   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3717   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);
3718   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);
3719   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);
3720   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");
3721   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3722   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3723   MatCheckPreallocated(A, 1);
3724 
3725   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3726   if (!A->ops->matsolvetranspose) {
3727     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3728     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3729   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3730   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3731   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3732   PetscFunctionReturn(PETSC_SUCCESS);
3733 }
3734 
3735 /*@
3736    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3737 
3738    Neighbor-wise Collective
3739 
3740    Input Parameters:
3741 +  A - the factored matrix
3742 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3743 
3744    Output Parameter:
3745 .  X - the result matrix (dense matrix)
3746 
3747    Level: developer
3748 
3749    Note:
3750    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
3751    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3752 
3753 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3754 @*/
3755 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3756 {
3757   PetscFunctionBegin;
3758   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3759   PetscValidType(A, 1);
3760   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3761   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3762   PetscCheckSameComm(A, 1, Bt, 2);
3763   PetscCheckSameComm(A, 1, X, 3);
3764 
3765   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3766   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);
3767   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);
3768   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");
3769   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3770   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3771   MatCheckPreallocated(A, 1);
3772 
3773   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3774   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3775   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3776   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3777   PetscFunctionReturn(PETSC_SUCCESS);
3778 }
3779 
3780 /*@
3781    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3782                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3783 
3784    Neighbor-wise Collective
3785 
3786    Input Parameters:
3787 +  mat - the factored matrix
3788 -  b - the right-hand-side vector
3789 
3790    Output Parameter:
3791 .  x - the result vector
3792 
3793    Level: developer
3794 
3795    Notes:
3796    `MatSolve()` should be used for most applications, as it performs
3797    a forward solve followed by a backward solve.
3798 
3799    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3800    call `MatForwardSolve`(A,x,x).
3801 
3802    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3803    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3804    `MatForwardSolve()` solves U^T*D y = b, and
3805    `MatBackwardSolve()` solves U x = y.
3806    Thus they do not provide a symmetric preconditioner.
3807 
3808 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3809 @*/
3810 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3811 {
3812   PetscFunctionBegin;
3813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3814   PetscValidType(mat, 1);
3815   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3816   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3817   PetscCheckSameComm(mat, 1, b, 2);
3818   PetscCheckSameComm(mat, 1, x, 3);
3819   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3820   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3821   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3822   PetscCheck(mat->rmap->n == 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);
3823   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3824   MatCheckPreallocated(mat, 1);
3825 
3826   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3827   PetscUseTypeMethod(mat, forwardsolve, b, x);
3828   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3829   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3830   PetscFunctionReturn(PETSC_SUCCESS);
3831 }
3832 
3833 /*@
3834    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3835                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3836 
3837    Neighbor-wise Collective
3838 
3839    Input Parameters:
3840 +  mat - the factored matrix
3841 -  b - the right-hand-side vector
3842 
3843    Output Parameter:
3844 .  x - the result vector
3845 
3846    Level: developer
3847 
3848    Notes:
3849    `MatSolve()` should be used for most applications, as it performs
3850    a forward solve followed by a backward solve.
3851 
3852    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3853    call `MatBackwardSolve`(A,x,x).
3854 
3855    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3856    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3857    `MatForwardSolve()` solves U^T*D y = b, and
3858    `MatBackwardSolve()` solves U x = y.
3859    Thus they do not provide a symmetric preconditioner.
3860 
3861 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3862 @*/
3863 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3864 {
3865   PetscFunctionBegin;
3866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3867   PetscValidType(mat, 1);
3868   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3869   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3870   PetscCheckSameComm(mat, 1, b, 2);
3871   PetscCheckSameComm(mat, 1, x, 3);
3872   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3873   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);
3874   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);
3875   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);
3876   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3877   MatCheckPreallocated(mat, 1);
3878 
3879   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3880   PetscUseTypeMethod(mat, backwardsolve, b, x);
3881   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3882   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3883   PetscFunctionReturn(PETSC_SUCCESS);
3884 }
3885 
3886 /*@
3887    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3888 
3889    Neighbor-wise Collective
3890 
3891    Input Parameters:
3892 +  mat - the factored matrix
3893 .  b - the right-hand-side vector
3894 -  y - the vector to be added to
3895 
3896    Output Parameter:
3897 .  x - the result vector
3898 
3899    Level: developer
3900 
3901    Note:
3902    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3903    call `MatSolveAdd`(A,x,y,x).
3904 
3905 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3906 @*/
3907 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3908 {
3909   PetscScalar one = 1.0;
3910   Vec         tmp;
3911 
3912   PetscFunctionBegin;
3913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3914   PetscValidType(mat, 1);
3915   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3916   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3917   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3918   PetscCheckSameComm(mat, 1, b, 2);
3919   PetscCheckSameComm(mat, 1, y, 3);
3920   PetscCheckSameComm(mat, 1, x, 4);
3921   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3922   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);
3923   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);
3924   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);
3925   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);
3926   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);
3927   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3928   MatCheckPreallocated(mat, 1);
3929 
3930   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3931   if (mat->factorerrortype) {
3932     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3933     PetscCall(VecSetInf(x));
3934   } else if (mat->ops->solveadd) {
3935     PetscUseTypeMethod(mat, solveadd, b, y, x);
3936   } else {
3937     /* do the solve then the add manually */
3938     if (x != y) {
3939       PetscCall(MatSolve(mat, b, x));
3940       PetscCall(VecAXPY(x, one, y));
3941     } else {
3942       PetscCall(VecDuplicate(x, &tmp));
3943       PetscCall(VecCopy(x, tmp));
3944       PetscCall(MatSolve(mat, b, x));
3945       PetscCall(VecAXPY(x, one, tmp));
3946       PetscCall(VecDestroy(&tmp));
3947     }
3948   }
3949   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3950   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3951   PetscFunctionReturn(PETSC_SUCCESS);
3952 }
3953 
3954 /*@
3955    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3956 
3957    Neighbor-wise Collective
3958 
3959    Input Parameters:
3960 +  mat - the factored matrix
3961 -  b - the right-hand-side vector
3962 
3963    Output Parameter:
3964 .  x - the result vector
3965 
3966    Level: developer
3967 
3968    Notes:
3969    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3970    call `MatSolveTranspose`(A,x,x).
3971 
3972    Most users should employ the `KSP` interface for linear solvers
3973    instead of working directly with matrix algebra routines such as this.
3974    See, e.g., `KSPCreate()`.
3975 
3976 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3977 @*/
3978 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3979 {
3980   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3981 
3982   PetscFunctionBegin;
3983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3984   PetscValidType(mat, 1);
3985   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3986   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3987   PetscCheckSameComm(mat, 1, b, 2);
3988   PetscCheckSameComm(mat, 1, x, 3);
3989   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3990   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);
3991   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);
3992   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3993   MatCheckPreallocated(mat, 1);
3994   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3995   if (mat->factorerrortype) {
3996     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3997     PetscCall(VecSetInf(x));
3998   } else {
3999     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4000     PetscCall((*f)(mat, b, x));
4001   }
4002   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4003   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4004   PetscFunctionReturn(PETSC_SUCCESS);
4005 }
4006 
4007 /*@
4008    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4009                       factored matrix.
4010 
4011    Neighbor-wise Collective
4012 
4013    Input Parameters:
4014 +  mat - the factored matrix
4015 .  b - the right-hand-side vector
4016 -  y - the vector to be added to
4017 
4018    Output Parameter:
4019 .  x - the result vector
4020 
4021    Level: developer
4022 
4023    Note:
4024    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4025    call `MatSolveTransposeAdd`(A,x,y,x).
4026 
4027 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4028 @*/
4029 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4030 {
4031   PetscScalar one = 1.0;
4032   Vec         tmp;
4033   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4034 
4035   PetscFunctionBegin;
4036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4037   PetscValidType(mat, 1);
4038   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4039   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4040   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4041   PetscCheckSameComm(mat, 1, b, 2);
4042   PetscCheckSameComm(mat, 1, y, 3);
4043   PetscCheckSameComm(mat, 1, x, 4);
4044   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4045   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);
4046   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);
4047   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);
4048   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);
4049   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4050   MatCheckPreallocated(mat, 1);
4051 
4052   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4053   if (mat->factorerrortype) {
4054     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4055     PetscCall(VecSetInf(x));
4056   } else if (f) {
4057     PetscCall((*f)(mat, b, y, x));
4058   } else {
4059     /* do the solve then the add manually */
4060     if (x != y) {
4061       PetscCall(MatSolveTranspose(mat, b, x));
4062       PetscCall(VecAXPY(x, one, y));
4063     } else {
4064       PetscCall(VecDuplicate(x, &tmp));
4065       PetscCall(VecCopy(x, tmp));
4066       PetscCall(MatSolveTranspose(mat, b, x));
4067       PetscCall(VecAXPY(x, one, tmp));
4068       PetscCall(VecDestroy(&tmp));
4069     }
4070   }
4071   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4072   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4073   PetscFunctionReturn(PETSC_SUCCESS);
4074 }
4075 
4076 /*@
4077    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4078 
4079    Neighbor-wise Collective
4080 
4081    Input Parameters:
4082 +  mat - the matrix
4083 .  b - the right hand side
4084 .  omega - the relaxation factor
4085 .  flag - flag indicating the type of SOR (see below)
4086 .  shift -  diagonal shift
4087 .  its - the number of iterations
4088 -  lits - the number of local iterations
4089 
4090    Output Parameter:
4091 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4092 
4093    SOR Flags:
4094 +     `SOR_FORWARD_SWEEP` - forward SOR
4095 .     `SOR_BACKWARD_SWEEP` - backward SOR
4096 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4097 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4098 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4099 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4100 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4101 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4102          upper/lower triangular part of matrix to
4103          vector (with omega)
4104 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4105 
4106    Level: developer
4107 
4108    Notes:
4109    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4110    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4111    on each processor.
4112 
4113    Application programmers will not generally use `MatSOR()` directly,
4114    but instead will employ the `KSP`/`PC` interface.
4115 
4116    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4117 
4118    Most users should employ the `KSP` interface for linear solvers
4119    instead of working directly with matrix algebra routines such as this.
4120    See, e.g., `KSPCreate()`.
4121 
4122    Vectors `x` and `b` CANNOT be the same
4123 
4124    The flags are implemented as bitwise inclusive or operations.
4125    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4126    to specify a zero initial guess for SSOR.
4127 
4128    Developer Note:
4129    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4130 
4131 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4132 @*/
4133 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4134 {
4135   PetscFunctionBegin;
4136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4137   PetscValidType(mat, 1);
4138   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4139   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4140   PetscCheckSameComm(mat, 1, b, 2);
4141   PetscCheckSameComm(mat, 1, x, 8);
4142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4143   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4144   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);
4145   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);
4146   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);
4147   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4148   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4149   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4150 
4151   MatCheckPreallocated(mat, 1);
4152   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4153   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4154   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4155   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4156   PetscFunctionReturn(PETSC_SUCCESS);
4157 }
4158 
4159 /*
4160       Default matrix copy routine.
4161 */
4162 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4163 {
4164   PetscInt           i, rstart = 0, rend = 0, nz;
4165   const PetscInt    *cwork;
4166   const PetscScalar *vwork;
4167 
4168   PetscFunctionBegin;
4169   if (B->assembled) PetscCall(MatZeroEntries(B));
4170   if (str == SAME_NONZERO_PATTERN) {
4171     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4172     for (i = rstart; i < rend; i++) {
4173       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4174       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4175       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4176     }
4177   } else {
4178     PetscCall(MatAYPX(B, 0.0, A, str));
4179   }
4180   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4181   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4182   PetscFunctionReturn(PETSC_SUCCESS);
4183 }
4184 
4185 /*@
4186    MatCopy - Copies a matrix to another matrix.
4187 
4188    Collective
4189 
4190    Input Parameters:
4191 +  A - the matrix
4192 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4193 
4194    Output Parameter:
4195 .  B - where the copy is put
4196 
4197    Level: intermediate
4198 
4199    Notes:
4200    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4201 
4202    `MatCopy()` copies the matrix entries of a matrix to another existing
4203    matrix (after first zeroing the second matrix).  A related routine is
4204    `MatConvert()`, which first creates a new matrix and then copies the data.
4205 
4206 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4207 @*/
4208 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4209 {
4210   PetscInt i;
4211 
4212   PetscFunctionBegin;
4213   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4214   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4215   PetscValidType(A, 1);
4216   PetscValidType(B, 2);
4217   PetscCheckSameComm(A, 1, B, 2);
4218   MatCheckPreallocated(B, 2);
4219   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4220   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4221   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,
4222              A->cmap->N, B->cmap->N);
4223   MatCheckPreallocated(A, 1);
4224   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4225 
4226   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4227   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4228   else PetscCall(MatCopy_Basic(A, B, str));
4229 
4230   B->stencil.dim = A->stencil.dim;
4231   B->stencil.noc = A->stencil.noc;
4232   for (i = 0; i <= A->stencil.dim; i++) {
4233     B->stencil.dims[i]   = A->stencil.dims[i];
4234     B->stencil.starts[i] = A->stencil.starts[i];
4235   }
4236 
4237   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4238   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4239   PetscFunctionReturn(PETSC_SUCCESS);
4240 }
4241 
4242 /*@C
4243    MatConvert - Converts a matrix to another matrix, either of the same
4244    or different type.
4245 
4246    Collective
4247 
4248    Input Parameters:
4249 +  mat - the matrix
4250 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4251    same type as the original matrix.
4252 -  reuse - denotes if the destination matrix is to be created or reused.
4253    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
4254    `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).
4255 
4256    Output Parameter:
4257 .  M - pointer to place new matrix
4258 
4259    Level: intermediate
4260 
4261    Notes:
4262    `MatConvert()` first creates a new matrix and then copies the data from
4263    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4264    entries of one matrix to another already existing matrix context.
4265 
4266    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4267    the MPI communicator of the generated matrix is always the same as the communicator
4268    of the input matrix.
4269 
4270 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4271 @*/
4272 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4273 {
4274   PetscBool  sametype, issame, flg;
4275   PetscBool3 issymmetric, ishermitian;
4276   char       convname[256], mtype[256];
4277   Mat        B;
4278 
4279   PetscFunctionBegin;
4280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4281   PetscValidType(mat, 1);
4282   PetscValidPointer(M, 4);
4283   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4284   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4285   MatCheckPreallocated(mat, 1);
4286 
4287   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4288   if (flg) newtype = mtype;
4289 
4290   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4291   PetscCall(PetscStrcmp(newtype, "same", &issame));
4292   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4293   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");
4294 
4295   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4296     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4297     PetscFunctionReturn(PETSC_SUCCESS);
4298   }
4299 
4300   /* Cache Mat options because some converters use MatHeaderReplace  */
4301   issymmetric = mat->symmetric;
4302   ishermitian = mat->hermitian;
4303 
4304   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4305     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4306     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4307   } else {
4308     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4309     const char *prefix[3]                                 = {"seq", "mpi", ""};
4310     PetscInt    i;
4311     /*
4312        Order of precedence:
4313        0) See if newtype is a superclass of the current matrix.
4314        1) See if a specialized converter is known to the current matrix.
4315        2) See if a specialized converter is known to the desired matrix class.
4316        3) See if a good general converter is registered for the desired class
4317           (as of 6/27/03 only MATMPIADJ falls into this category).
4318        4) See if a good general converter is known for the current matrix.
4319        5) Use a really basic converter.
4320     */
4321 
4322     /* 0) See if newtype is a superclass of the current matrix.
4323           i.e mat is mpiaij and newtype is aij */
4324     for (i = 0; i < 2; i++) {
4325       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4326       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4327       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4328       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4329       if (flg) {
4330         if (reuse == MAT_INPLACE_MATRIX) {
4331           PetscCall(PetscInfo(mat, "Early return\n"));
4332           PetscFunctionReturn(PETSC_SUCCESS);
4333         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4334           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4335           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4336           PetscFunctionReturn(PETSC_SUCCESS);
4337         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4338           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4339           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4340           PetscFunctionReturn(PETSC_SUCCESS);
4341         }
4342       }
4343     }
4344     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4345     for (i = 0; i < 3; i++) {
4346       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4347       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4352       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4353       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4354       if (conv) goto foundconv;
4355     }
4356 
4357     /* 2)  See if a specialized converter is known to the desired matrix class. */
4358     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4359     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4360     PetscCall(MatSetType(B, newtype));
4361     for (i = 0; i < 3; i++) {
4362       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4368       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4369       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4370       if (conv) {
4371         PetscCall(MatDestroy(&B));
4372         goto foundconv;
4373       }
4374     }
4375 
4376     /* 3) See if a good general converter is registered for the desired class */
4377     conv = B->ops->convertfrom;
4378     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4379     PetscCall(MatDestroy(&B));
4380     if (conv) goto foundconv;
4381 
4382     /* 4) See if a good general converter is known for the current matrix */
4383     if (mat->ops->convert) conv = mat->ops->convert;
4384     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4385     if (conv) goto foundconv;
4386 
4387     /* 5) Use a really basic converter. */
4388     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4389     conv = MatConvert_Basic;
4390 
4391   foundconv:
4392     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4393     PetscCall((*conv)(mat, newtype, reuse, M));
4394     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4395       /* the block sizes must be same if the mappings are copied over */
4396       (*M)->rmap->bs = mat->rmap->bs;
4397       (*M)->cmap->bs = mat->cmap->bs;
4398       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4399       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4400       (*M)->rmap->mapping = mat->rmap->mapping;
4401       (*M)->cmap->mapping = mat->cmap->mapping;
4402     }
4403     (*M)->stencil.dim = mat->stencil.dim;
4404     (*M)->stencil.noc = mat->stencil.noc;
4405     for (i = 0; i <= mat->stencil.dim; i++) {
4406       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4407       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4408     }
4409     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4410   }
4411   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4412 
4413   /* Copy Mat options */
4414   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4415   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4416   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4417   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4418   PetscFunctionReturn(PETSC_SUCCESS);
4419 }
4420 
4421 /*@C
4422    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4423 
4424    Not Collective
4425 
4426    Input Parameter:
4427 .  mat - the matrix, must be a factored matrix
4428 
4429    Output Parameter:
4430 .   type - the string name of the package (do not free this string)
4431 
4432    Level: intermediate
4433 
4434    Fortran Note:
4435    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4436 
4437 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4438 @*/
4439 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4440 {
4441   PetscErrorCode (*conv)(Mat, MatSolverType *);
4442 
4443   PetscFunctionBegin;
4444   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4445   PetscValidType(mat, 1);
4446   PetscValidPointer(type, 2);
4447   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4448   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4449   if (conv) PetscCall((*conv)(mat, type));
4450   else *type = MATSOLVERPETSC;
4451   PetscFunctionReturn(PETSC_SUCCESS);
4452 }
4453 
4454 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4455 struct _MatSolverTypeForSpecifcType {
4456   MatType mtype;
4457   /* no entry for MAT_FACTOR_NONE */
4458   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4459   MatSolverTypeForSpecifcType next;
4460 };
4461 
4462 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4463 struct _MatSolverTypeHolder {
4464   char                       *name;
4465   MatSolverTypeForSpecifcType handlers;
4466   MatSolverTypeHolder         next;
4467 };
4468 
4469 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4470 
4471 /*@C
4472    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4473 
4474    Input Parameters:
4475 +    package - name of the package, for example petsc or superlu
4476 .    mtype - the matrix type that works with this package
4477 .    ftype - the type of factorization supported by the package
4478 -    createfactor - routine that will create the factored matrix ready to be used
4479 
4480     Level: developer
4481 
4482 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4483 @*/
4484 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4485 {
4486   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4487   PetscBool                   flg;
4488   MatSolverTypeForSpecifcType inext, iprev = NULL;
4489 
4490   PetscFunctionBegin;
4491   PetscCall(MatInitializePackage());
4492   if (!next) {
4493     PetscCall(PetscNew(&MatSolverTypeHolders));
4494     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4495     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4496     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4497     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4498     PetscFunctionReturn(PETSC_SUCCESS);
4499   }
4500   while (next) {
4501     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4502     if (flg) {
4503       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4504       inext = next->handlers;
4505       while (inext) {
4506         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4507         if (flg) {
4508           inext->createfactor[(int)ftype - 1] = createfactor;
4509           PetscFunctionReturn(PETSC_SUCCESS);
4510         }
4511         iprev = inext;
4512         inext = inext->next;
4513       }
4514       PetscCall(PetscNew(&iprev->next));
4515       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4516       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4517       PetscFunctionReturn(PETSC_SUCCESS);
4518     }
4519     prev = next;
4520     next = next->next;
4521   }
4522   PetscCall(PetscNew(&prev->next));
4523   PetscCall(PetscStrallocpy(package, &prev->next->name));
4524   PetscCall(PetscNew(&prev->next->handlers));
4525   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4526   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4527   PetscFunctionReturn(PETSC_SUCCESS);
4528 }
4529 
4530 /*@C
4531    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4532 
4533    Input Parameters:
4534 +    type - name of the package, for example petsc or superlu
4535 .    ftype - the type of factorization supported by the type
4536 -    mtype - the matrix type that works with this type
4537 
4538    Output Parameters:
4539 +   foundtype - `PETSC_TRUE` if the type was registered
4540 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4541 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4542 
4543     Level: developer
4544 
4545 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4546 @*/
4547 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4548 {
4549   MatSolverTypeHolder         next = MatSolverTypeHolders;
4550   PetscBool                   flg;
4551   MatSolverTypeForSpecifcType inext;
4552 
4553   PetscFunctionBegin;
4554   if (foundtype) *foundtype = PETSC_FALSE;
4555   if (foundmtype) *foundmtype = PETSC_FALSE;
4556   if (createfactor) *createfactor = NULL;
4557 
4558   if (type) {
4559     while (next) {
4560       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4561       if (flg) {
4562         if (foundtype) *foundtype = PETSC_TRUE;
4563         inext = next->handlers;
4564         while (inext) {
4565           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4566           if (flg) {
4567             if (foundmtype) *foundmtype = PETSC_TRUE;
4568             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4569             PetscFunctionReturn(PETSC_SUCCESS);
4570           }
4571           inext = inext->next;
4572         }
4573       }
4574       next = next->next;
4575     }
4576   } else {
4577     while (next) {
4578       inext = next->handlers;
4579       while (inext) {
4580         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4581         if (flg && inext->createfactor[(int)ftype - 1]) {
4582           if (foundtype) *foundtype = PETSC_TRUE;
4583           if (foundmtype) *foundmtype = PETSC_TRUE;
4584           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4585           PetscFunctionReturn(PETSC_SUCCESS);
4586         }
4587         inext = inext->next;
4588       }
4589       next = next->next;
4590     }
4591     /* try with base classes inext->mtype */
4592     next = MatSolverTypeHolders;
4593     while (next) {
4594       inext = next->handlers;
4595       while (inext) {
4596         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4597         if (flg && inext->createfactor[(int)ftype - 1]) {
4598           if (foundtype) *foundtype = PETSC_TRUE;
4599           if (foundmtype) *foundmtype = PETSC_TRUE;
4600           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4601           PetscFunctionReturn(PETSC_SUCCESS);
4602         }
4603         inext = inext->next;
4604       }
4605       next = next->next;
4606     }
4607   }
4608   PetscFunctionReturn(PETSC_SUCCESS);
4609 }
4610 
4611 PetscErrorCode MatSolverTypeDestroy(void)
4612 {
4613   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4614   MatSolverTypeForSpecifcType inext, iprev;
4615 
4616   PetscFunctionBegin;
4617   while (next) {
4618     PetscCall(PetscFree(next->name));
4619     inext = next->handlers;
4620     while (inext) {
4621       PetscCall(PetscFree(inext->mtype));
4622       iprev = inext;
4623       inext = inext->next;
4624       PetscCall(PetscFree(iprev));
4625     }
4626     prev = next;
4627     next = next->next;
4628     PetscCall(PetscFree(prev));
4629   }
4630   MatSolverTypeHolders = NULL;
4631   PetscFunctionReturn(PETSC_SUCCESS);
4632 }
4633 
4634 /*@C
4635    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4636 
4637    Logically Collective
4638 
4639    Input Parameter:
4640 .  mat - the matrix
4641 
4642    Output Parameter:
4643 .  flg - `PETSC_TRUE` if uses the ordering
4644 
4645    Level: developer
4646 
4647    Note:
4648    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4649    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4650 
4651 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4652 @*/
4653 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4654 {
4655   PetscFunctionBegin;
4656   *flg = mat->canuseordering;
4657   PetscFunctionReturn(PETSC_SUCCESS);
4658 }
4659 
4660 /*@C
4661    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4662 
4663    Logically Collective
4664 
4665    Input Parameters:
4666 +  mat - the matrix obtained with `MatGetFactor()`
4667 -  ftype - the factorization type to be used
4668 
4669    Output Parameter:
4670 .  otype - the preferred ordering type
4671 
4672    Level: developer
4673 
4674 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4675 @*/
4676 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4677 {
4678   PetscFunctionBegin;
4679   *otype = mat->preferredordering[ftype];
4680   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4681   PetscFunctionReturn(PETSC_SUCCESS);
4682 }
4683 
4684 /*@C
4685    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4686 
4687    Collective
4688 
4689    Input Parameters:
4690 +  mat - the matrix
4691 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4692 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4693 
4694    Output Parameter:
4695 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4696 
4697    Options Database Key:
4698 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4699                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4700 
4701    Level: intermediate
4702 
4703    Notes:
4704      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4705      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4706 
4707      Users usually access the factorization solvers via `KSP`
4708 
4709       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4710      such as pastix, superlu, mumps etc.
4711 
4712       PETSc must have been ./configure to use the external solver, using the option --download-package
4713 
4714       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4715       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4716       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4717 
4718    Developer Note:
4719       This should actually be called `MatCreateFactor()` since it creates a new factor object
4720 
4721 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4722           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4723 @*/
4724 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4725 {
4726   PetscBool foundtype, foundmtype;
4727   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4728 
4729   PetscFunctionBegin;
4730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4731   PetscValidType(mat, 1);
4732 
4733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4734   MatCheckPreallocated(mat, 1);
4735 
4736   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4737   if (!foundtype) {
4738     if (type) {
4739       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],
4740               ((PetscObject)mat)->type_name, type);
4741     } else {
4742       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);
4743     }
4744   }
4745   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4746   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);
4747 
4748   PetscCall((*conv)(mat, ftype, f));
4749   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4750   PetscFunctionReturn(PETSC_SUCCESS);
4751 }
4752 
4753 /*@C
4754    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4755 
4756    Not Collective
4757 
4758    Input Parameters:
4759 +  mat - the matrix
4760 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4761 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4762 
4763    Output Parameter:
4764 .    flg - PETSC_TRUE if the factorization is available
4765 
4766    Level: intermediate
4767 
4768    Notes:
4769       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4770      such as pastix, superlu, mumps etc.
4771 
4772       PETSc must have been ./configure to use the external solver, using the option --download-package
4773 
4774    Developer Note:
4775       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4776 
4777 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4778           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4779 @*/
4780 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4781 {
4782   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4783 
4784   PetscFunctionBegin;
4785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4786   PetscValidType(mat, 1);
4787   PetscValidBoolPointer(flg, 4);
4788 
4789   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4790   MatCheckPreallocated(mat, 1);
4791 
4792   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4793   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4794   PetscFunctionReturn(PETSC_SUCCESS);
4795 }
4796 
4797 /*@
4798    MatDuplicate - Duplicates a matrix including the non-zero structure.
4799 
4800    Collective
4801 
4802    Input Parameters:
4803 +  mat - the matrix
4804 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4805         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4806 
4807    Output Parameter:
4808 .  M - pointer to place new matrix
4809 
4810    Level: intermediate
4811 
4812    Notes:
4813     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4814 
4815     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.
4816 
4817     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
4818     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4819     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4820 
4821 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4822 @*/
4823 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4824 {
4825   Mat         B;
4826   VecType     vtype;
4827   PetscInt    i;
4828   PetscObject dm;
4829   void (*viewf)(void);
4830 
4831   PetscFunctionBegin;
4832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4833   PetscValidType(mat, 1);
4834   PetscValidPointer(M, 3);
4835   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4836   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4837   MatCheckPreallocated(mat, 1);
4838 
4839   *M = NULL;
4840   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4841   PetscUseTypeMethod(mat, duplicate, op, M);
4842   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4843   B = *M;
4844 
4845   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4846   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4847   PetscCall(MatGetVecType(mat, &vtype));
4848   PetscCall(MatSetVecType(B, vtype));
4849 
4850   B->stencil.dim = mat->stencil.dim;
4851   B->stencil.noc = mat->stencil.noc;
4852   for (i = 0; i <= mat->stencil.dim; i++) {
4853     B->stencil.dims[i]   = mat->stencil.dims[i];
4854     B->stencil.starts[i] = mat->stencil.starts[i];
4855   }
4856 
4857   B->nooffproczerorows = mat->nooffproczerorows;
4858   B->nooffprocentries  = mat->nooffprocentries;
4859 
4860   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4861   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4862   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4863   PetscFunctionReturn(PETSC_SUCCESS);
4864 }
4865 
4866 /*@
4867    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4868 
4869    Logically Collective
4870 
4871    Input Parameter:
4872 .  mat - the matrix
4873 
4874    Output Parameter:
4875 .  v - the diagonal of the matrix
4876 
4877    Level: intermediate
4878 
4879    Note:
4880    Currently only correct in parallel for square matrices.
4881 
4882 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4883 @*/
4884 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4885 {
4886   PetscFunctionBegin;
4887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4888   PetscValidType(mat, 1);
4889   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4890   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4891   MatCheckPreallocated(mat, 1);
4892 
4893   PetscUseTypeMethod(mat, getdiagonal, v);
4894   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4895   PetscFunctionReturn(PETSC_SUCCESS);
4896 }
4897 
4898 /*@C
4899    MatGetRowMin - Gets the minimum value (of the real part) of each
4900         row of the matrix
4901 
4902    Logically Collective
4903 
4904    Input Parameter:
4905 .  mat - the matrix
4906 
4907    Output Parameters:
4908 +  v - the vector for storing the maximums
4909 -  idx - the indices of the column found for each row (optional)
4910 
4911    Level: intermediate
4912 
4913    Note:
4914     The result of this call are the same as if one converted the matrix to dense format
4915       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4916 
4917     This code is only implemented for a couple of matrix formats.
4918 
4919 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4920           `MatGetRowMax()`
4921 @*/
4922 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4923 {
4924   PetscFunctionBegin;
4925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4926   PetscValidType(mat, 1);
4927   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4928   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4929 
4930   if (!mat->cmap->N) {
4931     PetscCall(VecSet(v, PETSC_MAX_REAL));
4932     if (idx) {
4933       PetscInt i, m = mat->rmap->n;
4934       for (i = 0; i < m; i++) idx[i] = -1;
4935     }
4936   } else {
4937     MatCheckPreallocated(mat, 1);
4938   }
4939   PetscUseTypeMethod(mat, getrowmin, v, idx);
4940   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4941   PetscFunctionReturn(PETSC_SUCCESS);
4942 }
4943 
4944 /*@C
4945    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4946         row of the matrix
4947 
4948    Logically Collective
4949 
4950    Input Parameter:
4951 .  mat - the matrix
4952 
4953    Output Parameters:
4954 +  v - the vector for storing the minimums
4955 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4956 
4957    Level: intermediate
4958 
4959    Notes:
4960     if a row is completely empty or has only 0.0 values then the idx[] value for that
4961     row is 0 (the first column).
4962 
4963     This code is only implemented for a couple of matrix formats.
4964 
4965 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4966 @*/
4967 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4968 {
4969   PetscFunctionBegin;
4970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4971   PetscValidType(mat, 1);
4972   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4973   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4974   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4975 
4976   if (!mat->cmap->N) {
4977     PetscCall(VecSet(v, 0.0));
4978     if (idx) {
4979       PetscInt i, m = mat->rmap->n;
4980       for (i = 0; i < m; i++) idx[i] = -1;
4981     }
4982   } else {
4983     MatCheckPreallocated(mat, 1);
4984     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4985     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4986   }
4987   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4988   PetscFunctionReturn(PETSC_SUCCESS);
4989 }
4990 
4991 /*@C
4992    MatGetRowMax - Gets the maximum value (of the real part) of each
4993         row of the matrix
4994 
4995    Logically Collective
4996 
4997    Input Parameter:
4998 .  mat - the matrix
4999 
5000    Output Parameters:
5001 +  v - the vector for storing the maximums
5002 -  idx - the indices of the column found for each row (optional)
5003 
5004    Level: intermediate
5005 
5006    Notes:
5007     The result of this call are the same as if one converted the matrix to dense format
5008       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5009 
5010     This code is only implemented for a couple of matrix formats.
5011 
5012 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5013 @*/
5014 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5015 {
5016   PetscFunctionBegin;
5017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5018   PetscValidType(mat, 1);
5019   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5020   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5021 
5022   if (!mat->cmap->N) {
5023     PetscCall(VecSet(v, PETSC_MIN_REAL));
5024     if (idx) {
5025       PetscInt i, m = mat->rmap->n;
5026       for (i = 0; i < m; i++) idx[i] = -1;
5027     }
5028   } else {
5029     MatCheckPreallocated(mat, 1);
5030     PetscUseTypeMethod(mat, getrowmax, v, idx);
5031   }
5032   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5033   PetscFunctionReturn(PETSC_SUCCESS);
5034 }
5035 
5036 /*@C
5037    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5038         row of the matrix
5039 
5040    Logically Collective
5041 
5042    Input Parameter:
5043 .  mat - the matrix
5044 
5045    Output Parameters:
5046 +  v - the vector for storing the maximums
5047 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5048 
5049    Level: intermediate
5050 
5051    Notes:
5052     if a row is completely empty or has only 0.0 values then the idx[] value for that
5053     row is 0 (the first column).
5054 
5055     This code is only implemented for a couple of matrix formats.
5056 
5057 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5058 @*/
5059 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5060 {
5061   PetscFunctionBegin;
5062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5063   PetscValidType(mat, 1);
5064   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5065   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5066 
5067   if (!mat->cmap->N) {
5068     PetscCall(VecSet(v, 0.0));
5069     if (idx) {
5070       PetscInt i, m = mat->rmap->n;
5071       for (i = 0; i < m; i++) idx[i] = -1;
5072     }
5073   } else {
5074     MatCheckPreallocated(mat, 1);
5075     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5076     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5077   }
5078   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5079   PetscFunctionReturn(PETSC_SUCCESS);
5080 }
5081 
5082 /*@
5083    MatGetRowSum - Gets the sum of each row of the matrix
5084 
5085    Logically or Neighborhood Collective
5086 
5087    Input Parameter:
5088 .  mat - the matrix
5089 
5090    Output Parameter:
5091 .  v - the vector for storing the sum of rows
5092 
5093    Level: intermediate
5094 
5095    Notes:
5096     This code is slow since it is not currently specialized for different formats
5097 
5098 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5099 @*/
5100 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5101 {
5102   Vec ones;
5103 
5104   PetscFunctionBegin;
5105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5106   PetscValidType(mat, 1);
5107   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5108   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5109   MatCheckPreallocated(mat, 1);
5110   PetscCall(MatCreateVecs(mat, &ones, NULL));
5111   PetscCall(VecSet(ones, 1.));
5112   PetscCall(MatMult(mat, ones, v));
5113   PetscCall(VecDestroy(&ones));
5114   PetscFunctionReturn(PETSC_SUCCESS);
5115 }
5116 
5117 /*@
5118    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5119    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5120 
5121    Collective
5122 
5123    Input Parameter:
5124 .  mat - the matrix to provide the transpose
5125 
5126    Output Parameter:
5127 .  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
5128 
5129    Level: advanced
5130 
5131    Note:
5132    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
5133    routine allows bypassing that call.
5134 
5135 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5136 @*/
5137 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5138 {
5139   PetscContainer  rB = NULL;
5140   MatParentState *rb = NULL;
5141 
5142   PetscFunctionBegin;
5143   PetscCall(PetscNew(&rb));
5144   rb->id    = ((PetscObject)mat)->id;
5145   rb->state = 0;
5146   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5147   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5148   PetscCall(PetscContainerSetPointer(rB, rb));
5149   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5150   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5151   PetscCall(PetscObjectDereference((PetscObject)rB));
5152   PetscFunctionReturn(PETSC_SUCCESS);
5153 }
5154 
5155 /*@
5156    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5157 
5158    Collective
5159 
5160    Input Parameters:
5161 +  mat - the matrix to transpose
5162 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5163 
5164    Output Parameter:
5165 .  B - the transpose
5166 
5167    Level: intermediate
5168 
5169    Notes:
5170      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5171 
5172      `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
5173      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5174 
5175      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.
5176 
5177      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5178 
5179      If mat is unchanged from the last call this function returns immediately without recomputing the result
5180 
5181      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5182 
5183 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5184           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5185 @*/
5186 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5187 {
5188   PetscContainer  rB = NULL;
5189   MatParentState *rb = NULL;
5190 
5191   PetscFunctionBegin;
5192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5193   PetscValidType(mat, 1);
5194   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5195   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5196   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5197   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5198   MatCheckPreallocated(mat, 1);
5199   if (reuse == MAT_REUSE_MATRIX) {
5200     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5201     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5202     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5203     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5204     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5205   }
5206 
5207   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5208   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5209     PetscUseTypeMethod(mat, transpose, reuse, B);
5210     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5211   }
5212   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5213 
5214   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5215   if (reuse != MAT_INPLACE_MATRIX) {
5216     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5217     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5218     rb->state        = ((PetscObject)mat)->state;
5219     rb->nonzerostate = mat->nonzerostate;
5220   }
5221   PetscFunctionReturn(PETSC_SUCCESS);
5222 }
5223 
5224 /*@
5225    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5226 
5227    Collective
5228 
5229    Input Parameter:
5230 .  A - the matrix to transpose
5231 
5232    Output Parameter:
5233 .  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
5234       numerical portion.
5235 
5236    Level: intermediate
5237 
5238    Note:
5239    This is not supported for many matrix types, use `MatTranspose()` in those cases
5240 
5241 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5242 @*/
5243 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5244 {
5245   PetscFunctionBegin;
5246   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5247   PetscValidType(A, 1);
5248   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5249   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5250   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5251   PetscUseTypeMethod(A, transposesymbolic, B);
5252   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5253 
5254   PetscCall(MatTransposeSetPrecursor(A, *B));
5255   PetscFunctionReturn(PETSC_SUCCESS);
5256 }
5257 
5258 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5259 {
5260   PetscContainer  rB;
5261   MatParentState *rb;
5262 
5263   PetscFunctionBegin;
5264   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5265   PetscValidType(A, 1);
5266   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5267   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5268   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5269   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5270   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5271   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5272   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5273   PetscFunctionReturn(PETSC_SUCCESS);
5274 }
5275 
5276 /*@
5277    MatIsTranspose - Test whether a matrix is another one's transpose,
5278         or its own, in which case it tests symmetry.
5279 
5280    Collective
5281 
5282    Input Parameters:
5283 +  A - the matrix to test
5284 .  B - the matrix to test against, this can equal the first parameter
5285 -  tol - tolerance, differences between entries smaller than this are counted as zero
5286 
5287    Output Parameter:
5288 .  flg - the result
5289 
5290    Level: intermediate
5291 
5292    Notes:
5293    Only available for `MATAIJ` matrices.
5294 
5295    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5296    test involves parallel copies of the block-offdiagonal parts of the matrix.
5297 
5298 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5299 @*/
5300 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5301 {
5302   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5303 
5304   PetscFunctionBegin;
5305   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5306   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5307   PetscValidBoolPointer(flg, 4);
5308   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5309   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5310   *flg = PETSC_FALSE;
5311   if (f && g) {
5312     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5313     PetscCall((*f)(A, B, tol, flg));
5314   } else {
5315     MatType mattype;
5316 
5317     PetscCall(MatGetType(f ? B : A, &mattype));
5318     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5319   }
5320   PetscFunctionReturn(PETSC_SUCCESS);
5321 }
5322 
5323 /*@
5324    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5325 
5326    Collective
5327 
5328    Input Parameters:
5329 +  mat - the matrix to transpose and complex conjugate
5330 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5331 
5332    Output Parameter:
5333 .  B - the Hermitian transpose
5334 
5335    Level: intermediate
5336 
5337 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5338 @*/
5339 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5340 {
5341   PetscFunctionBegin;
5342   PetscCall(MatTranspose(mat, reuse, B));
5343 #if defined(PETSC_USE_COMPLEX)
5344   PetscCall(MatConjugate(*B));
5345 #endif
5346   PetscFunctionReturn(PETSC_SUCCESS);
5347 }
5348 
5349 /*@
5350    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5351 
5352    Collective
5353 
5354    Input Parameters:
5355 +  A - the matrix to test
5356 .  B - the matrix to test against, this can equal the first parameter
5357 -  tol - tolerance, differences between entries smaller than this are counted as zero
5358 
5359    Output Parameter:
5360 .  flg - the result
5361 
5362    Level: intermediate
5363 
5364    Notes:
5365    Only available for `MATAIJ` matrices.
5366 
5367    The sequential algorithm
5368    has a running time of the order of the number of nonzeros; the parallel
5369    test involves parallel copies of the block-offdiagonal parts of the matrix.
5370 
5371 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5372 @*/
5373 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5374 {
5375   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5376 
5377   PetscFunctionBegin;
5378   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5379   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5380   PetscValidBoolPointer(flg, 4);
5381   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5382   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5383   if (f && g) {
5384     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5385     PetscCall((*f)(A, B, tol, flg));
5386   }
5387   PetscFunctionReturn(PETSC_SUCCESS);
5388 }
5389 
5390 /*@
5391    MatPermute - Creates a new matrix with rows and columns permuted from the
5392    original.
5393 
5394    Collective
5395 
5396    Input Parameters:
5397 +  mat - the matrix to permute
5398 .  row - row permutation, each processor supplies only the permutation for its rows
5399 -  col - column permutation, each processor supplies only the permutation for its columns
5400 
5401    Output Parameter:
5402 .  B - the permuted matrix
5403 
5404    Level: advanced
5405 
5406    Note:
5407    The index sets map from row/col of permuted matrix to row/col of original matrix.
5408    The index sets should be on the same communicator as mat and have the same local sizes.
5409 
5410    Developer Note:
5411      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5412      exploit the fact that row and col are permutations, consider implementing the
5413      more general `MatCreateSubMatrix()` instead.
5414 
5415 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5416 @*/
5417 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5418 {
5419   PetscFunctionBegin;
5420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5421   PetscValidType(mat, 1);
5422   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5423   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5424   PetscValidPointer(B, 4);
5425   PetscCheckSameComm(mat, 1, row, 2);
5426   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5427   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5428   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5429   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5430   MatCheckPreallocated(mat, 1);
5431 
5432   if (mat->ops->permute) {
5433     PetscUseTypeMethod(mat, permute, row, col, B);
5434     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5435   } else {
5436     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5437   }
5438   PetscFunctionReturn(PETSC_SUCCESS);
5439 }
5440 
5441 /*@
5442    MatEqual - Compares two matrices.
5443 
5444    Collective
5445 
5446    Input Parameters:
5447 +  A - the first matrix
5448 -  B - the second matrix
5449 
5450    Output Parameter:
5451 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5452 
5453    Level: intermediate
5454 
5455 .seealso: [](chapter_matrices), `Mat`
5456 @*/
5457 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5458 {
5459   PetscFunctionBegin;
5460   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5461   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5462   PetscValidType(A, 1);
5463   PetscValidType(B, 2);
5464   PetscValidBoolPointer(flg, 3);
5465   PetscCheckSameComm(A, 1, B, 2);
5466   MatCheckPreallocated(A, 1);
5467   MatCheckPreallocated(B, 2);
5468   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5469   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5470   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,
5471              B->cmap->N);
5472   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5473     PetscUseTypeMethod(A, equal, B, flg);
5474   } else {
5475     PetscCall(MatMultEqual(A, B, 10, flg));
5476   }
5477   PetscFunctionReturn(PETSC_SUCCESS);
5478 }
5479 
5480 /*@
5481    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5482    matrices that are stored as vectors.  Either of the two scaling
5483    matrices can be `NULL`.
5484 
5485    Collective
5486 
5487    Input Parameters:
5488 +  mat - the matrix to be scaled
5489 .  l - the left scaling vector (or `NULL`)
5490 -  r - the right scaling vector (or `NULL`)
5491 
5492    Level: intermediate
5493 
5494    Note:
5495    `MatDiagonalScale()` computes A = LAR, where
5496    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5497    The L scales the rows of the matrix, the R scales the columns of the matrix.
5498 
5499 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5500 @*/
5501 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5502 {
5503   PetscFunctionBegin;
5504   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5505   PetscValidType(mat, 1);
5506   if (l) {
5507     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5508     PetscCheckSameComm(mat, 1, l, 2);
5509   }
5510   if (r) {
5511     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5512     PetscCheckSameComm(mat, 1, r, 3);
5513   }
5514   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5515   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5516   MatCheckPreallocated(mat, 1);
5517   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5518 
5519   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5520   PetscUseTypeMethod(mat, diagonalscale, l, r);
5521   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5522   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5523   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5524   PetscFunctionReturn(PETSC_SUCCESS);
5525 }
5526 
5527 /*@
5528     MatScale - Scales all elements of a matrix by a given number.
5529 
5530     Logically Collective
5531 
5532     Input Parameters:
5533 +   mat - the matrix to be scaled
5534 -   a  - the scaling value
5535 
5536     Level: intermediate
5537 
5538 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5539 @*/
5540 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5541 {
5542   PetscFunctionBegin;
5543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5544   PetscValidType(mat, 1);
5545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5547   PetscValidLogicalCollectiveScalar(mat, a, 2);
5548   MatCheckPreallocated(mat, 1);
5549 
5550   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5551   if (a != (PetscScalar)1.0) {
5552     PetscUseTypeMethod(mat, scale, a);
5553     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5554   }
5555   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5556   PetscFunctionReturn(PETSC_SUCCESS);
5557 }
5558 
5559 /*@
5560    MatNorm - Calculates various norms of a matrix.
5561 
5562    Collective
5563 
5564    Input Parameters:
5565 +  mat - the matrix
5566 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5567 
5568    Output Parameter:
5569 .  nrm - the resulting norm
5570 
5571    Level: intermediate
5572 
5573 .seealso: [](chapter_matrices), `Mat`
5574 @*/
5575 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5576 {
5577   PetscFunctionBegin;
5578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5579   PetscValidType(mat, 1);
5580   PetscValidRealPointer(nrm, 3);
5581 
5582   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5583   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5584   MatCheckPreallocated(mat, 1);
5585 
5586   PetscUseTypeMethod(mat, norm, type, nrm);
5587   PetscFunctionReturn(PETSC_SUCCESS);
5588 }
5589 
5590 /*
5591      This variable is used to prevent counting of MatAssemblyBegin() that
5592    are called from within a MatAssemblyEnd().
5593 */
5594 static PetscInt MatAssemblyEnd_InUse = 0;
5595 /*@
5596    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5597    be called after completing all calls to `MatSetValues()`.
5598 
5599    Collective
5600 
5601    Input Parameters:
5602 +  mat - the matrix
5603 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5604 
5605    Level: beginner
5606 
5607    Notes:
5608    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5609    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5610 
5611    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5612    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5613    using the matrix.
5614 
5615    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5616    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
5617    a global collective operation requiring all processes that share the matrix.
5618 
5619    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5620    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5621    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5622 
5623 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5624 @*/
5625 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5626 {
5627   PetscFunctionBegin;
5628   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5629   PetscValidType(mat, 1);
5630   MatCheckPreallocated(mat, 1);
5631   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5632   if (mat->assembled) {
5633     mat->was_assembled = PETSC_TRUE;
5634     mat->assembled     = PETSC_FALSE;
5635   }
5636 
5637   if (!MatAssemblyEnd_InUse) {
5638     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5639     PetscTryTypeMethod(mat, assemblybegin, type);
5640     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5641   } else PetscTryTypeMethod(mat, assemblybegin, type);
5642   PetscFunctionReturn(PETSC_SUCCESS);
5643 }
5644 
5645 /*@
5646    MatAssembled - Indicates if a matrix has been assembled and is ready for
5647      use; for example, in matrix-vector product.
5648 
5649    Not Collective
5650 
5651    Input Parameter:
5652 .  mat - the matrix
5653 
5654    Output Parameter:
5655 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5656 
5657    Level: advanced
5658 
5659 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5660 @*/
5661 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5662 {
5663   PetscFunctionBegin;
5664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5665   PetscValidBoolPointer(assembled, 2);
5666   *assembled = mat->assembled;
5667   PetscFunctionReturn(PETSC_SUCCESS);
5668 }
5669 
5670 /*@
5671    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5672    be called after `MatAssemblyBegin()`.
5673 
5674    Collective
5675 
5676    Input Parameters:
5677 +  mat - the matrix
5678 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5679 
5680    Options Database Keys:
5681 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5682 .  -mat_view ::ascii_info_detail - Prints more detailed info
5683 .  -mat_view - Prints matrix in ASCII format
5684 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5685 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5686 .  -display <name> - Sets display name (default is host)
5687 .  -draw_pause <sec> - Sets number of seconds to pause after display
5688 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5689 .  -viewer_socket_machine <machine> - Machine to use for socket
5690 .  -viewer_socket_port <port> - Port number to use for socket
5691 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5692 
5693    Level: beginner
5694 
5695 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5696 @*/
5697 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5698 {
5699   static PetscInt inassm = 0;
5700   PetscBool       flg    = PETSC_FALSE;
5701 
5702   PetscFunctionBegin;
5703   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5704   PetscValidType(mat, 1);
5705 
5706   inassm++;
5707   MatAssemblyEnd_InUse++;
5708   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5709     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5710     PetscTryTypeMethod(mat, assemblyend, type);
5711     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5712   } else PetscTryTypeMethod(mat, assemblyend, type);
5713 
5714   /* Flush assembly is not a true assembly */
5715   if (type != MAT_FLUSH_ASSEMBLY) {
5716     if (mat->num_ass) {
5717       if (!mat->symmetry_eternal) {
5718         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5719         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5720       }
5721       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5722       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5723     }
5724     mat->num_ass++;
5725     mat->assembled        = PETSC_TRUE;
5726     mat->ass_nonzerostate = mat->nonzerostate;
5727   }
5728 
5729   mat->insertmode = NOT_SET_VALUES;
5730   MatAssemblyEnd_InUse--;
5731   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5732   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5733     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5734 
5735     if (mat->checksymmetryonassembly) {
5736       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5737       if (flg) {
5738         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5739       } else {
5740         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5741       }
5742     }
5743     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5744   }
5745   inassm--;
5746   PetscFunctionReturn(PETSC_SUCCESS);
5747 }
5748 
5749 /*@
5750    MatSetOption - Sets a parameter option for a matrix. Some options
5751    may be specific to certain storage formats.  Some options
5752    determine how values will be inserted (or added). Sorted,
5753    row-oriented input will generally assemble the fastest. The default
5754    is row-oriented.
5755 
5756    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5757 
5758    Input Parameters:
5759 +  mat - the matrix
5760 .  option - the option, one of those listed below (and possibly others),
5761 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5762 
5763   Options Describing Matrix Structure:
5764 +    `MAT_SPD` - symmetric positive definite
5765 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5766 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5767 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5768 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5769 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5770 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5771 
5772    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5773    do not need to be computed (usually at a high cost)
5774 
5775    Options For Use with `MatSetValues()`:
5776    Insert a logically dense subblock, which can be
5777 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5778 
5779    These options reflect the data you pass in with `MatSetValues()`; it has
5780    nothing to do with how the data is stored internally in the matrix
5781    data structure.
5782 
5783    When (re)assembling a matrix, we can restrict the input for
5784    efficiency/debugging purposes.  These options include
5785 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5786 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5787 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5788 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5789 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5790 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5791         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5792         performance for very large process counts.
5793 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5794         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5795         functions, instead sending only neighbor messages.
5796 
5797    Level: intermediate
5798 
5799    Notes:
5800    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5801 
5802    Some options are relevant only for particular matrix types and
5803    are thus ignored by others.  Other options are not supported by
5804    certain matrix types and will generate an error message if set.
5805 
5806    If using Fortran to compute a matrix, one may need to
5807    use the column-oriented option (or convert to the row-oriented
5808    format).
5809 
5810    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5811    that would generate a new entry in the nonzero structure is instead
5812    ignored.  Thus, if memory has not already been allocated for this particular
5813    data, then the insertion is ignored. For dense matrices, in which
5814    the entire array is allocated, no entries are ever ignored.
5815    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5816 
5817    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5818    that would generate a new entry in the nonzero structure instead produces
5819    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
5820 
5821    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5822    that would generate a new entry that has not been preallocated will
5823    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5824    only.) This is a useful flag when debugging matrix memory preallocation.
5825    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5826 
5827    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5828    other processors should be dropped, rather than stashed.
5829    This is useful if you know that the "owning" processor is also
5830    always generating the correct matrix entries, so that PETSc need
5831    not transfer duplicate entries generated on another processor.
5832 
5833    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5834    searches during matrix assembly. When this flag is set, the hash table
5835    is created during the first matrix assembly. This hash table is
5836    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5837    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5838    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5839    supported by `MATMPIBAIJ` format only.
5840 
5841    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5842    are kept in the nonzero structure
5843 
5844    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5845    a zero location in the matrix
5846 
5847    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5848 
5849    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5850         zero row routines and thus improves performance for very large process counts.
5851 
5852    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5853         part of the matrix (since they should match the upper triangular part).
5854 
5855    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5856                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5857                      with finite difference schemes with non-periodic boundary conditions.
5858 
5859    Developer Note:
5860    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5861    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5862    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5863    not changed.
5864 
5865 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5866 @*/
5867 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5868 {
5869   PetscFunctionBegin;
5870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5871   if (op > 0) {
5872     PetscValidLogicalCollectiveEnum(mat, op, 2);
5873     PetscValidLogicalCollectiveBool(mat, flg, 3);
5874   }
5875 
5876   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);
5877 
5878   switch (op) {
5879   case MAT_FORCE_DIAGONAL_ENTRIES:
5880     mat->force_diagonals = flg;
5881     PetscFunctionReturn(PETSC_SUCCESS);
5882   case MAT_NO_OFF_PROC_ENTRIES:
5883     mat->nooffprocentries = flg;
5884     PetscFunctionReturn(PETSC_SUCCESS);
5885   case MAT_SUBSET_OFF_PROC_ENTRIES:
5886     mat->assembly_subset = flg;
5887     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5888 #if !defined(PETSC_HAVE_MPIUNI)
5889       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5890 #endif
5891       mat->stash.first_assembly_done = PETSC_FALSE;
5892     }
5893     PetscFunctionReturn(PETSC_SUCCESS);
5894   case MAT_NO_OFF_PROC_ZERO_ROWS:
5895     mat->nooffproczerorows = flg;
5896     PetscFunctionReturn(PETSC_SUCCESS);
5897   case MAT_SPD:
5898     if (flg) {
5899       mat->spd                    = PETSC_BOOL3_TRUE;
5900       mat->symmetric              = PETSC_BOOL3_TRUE;
5901       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5902     } else {
5903       mat->spd = PETSC_BOOL3_FALSE;
5904     }
5905     break;
5906   case MAT_SYMMETRIC:
5907     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5908     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5909 #if !defined(PETSC_USE_COMPLEX)
5910     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5911 #endif
5912     break;
5913   case MAT_HERMITIAN:
5914     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5915     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5916 #if !defined(PETSC_USE_COMPLEX)
5917     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5918 #endif
5919     break;
5920   case MAT_STRUCTURALLY_SYMMETRIC:
5921     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5922     break;
5923   case MAT_SYMMETRY_ETERNAL:
5924     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");
5925     mat->symmetry_eternal = flg;
5926     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5927     break;
5928   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5929     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");
5930     mat->structural_symmetry_eternal = flg;
5931     break;
5932   case MAT_SPD_ETERNAL:
5933     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");
5934     mat->spd_eternal = flg;
5935     if (flg) {
5936       mat->structural_symmetry_eternal = PETSC_TRUE;
5937       mat->symmetry_eternal            = PETSC_TRUE;
5938     }
5939     break;
5940   case MAT_STRUCTURE_ONLY:
5941     mat->structure_only = flg;
5942     break;
5943   case MAT_SORTED_FULL:
5944     mat->sortedfull = flg;
5945     break;
5946   default:
5947     break;
5948   }
5949   PetscTryTypeMethod(mat, setoption, op, flg);
5950   PetscFunctionReturn(PETSC_SUCCESS);
5951 }
5952 
5953 /*@
5954    MatGetOption - Gets a parameter option that has been set for a matrix.
5955 
5956    Logically Collective
5957 
5958    Input Parameters:
5959 +  mat - the matrix
5960 -  option - the option, this only responds to certain options, check the code for which ones
5961 
5962    Output Parameter:
5963 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5964 
5965    Level: intermediate
5966 
5967     Notes:
5968     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5969 
5970     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5971     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5972 
5973 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5974     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5975 @*/
5976 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5977 {
5978   PetscFunctionBegin;
5979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5980   PetscValidType(mat, 1);
5981 
5982   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);
5983   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()");
5984 
5985   switch (op) {
5986   case MAT_NO_OFF_PROC_ENTRIES:
5987     *flg = mat->nooffprocentries;
5988     break;
5989   case MAT_NO_OFF_PROC_ZERO_ROWS:
5990     *flg = mat->nooffproczerorows;
5991     break;
5992   case MAT_SYMMETRIC:
5993     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5994     break;
5995   case MAT_HERMITIAN:
5996     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5997     break;
5998   case MAT_STRUCTURALLY_SYMMETRIC:
5999     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6000     break;
6001   case MAT_SPD:
6002     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6003     break;
6004   case MAT_SYMMETRY_ETERNAL:
6005     *flg = mat->symmetry_eternal;
6006     break;
6007   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6008     *flg = mat->symmetry_eternal;
6009     break;
6010   default:
6011     break;
6012   }
6013   PetscFunctionReturn(PETSC_SUCCESS);
6014 }
6015 
6016 /*@
6017    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6018    this routine retains the old nonzero structure.
6019 
6020    Logically Collective
6021 
6022    Input Parameter:
6023 .  mat - the matrix
6024 
6025    Level: intermediate
6026 
6027    Note:
6028     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.
6029    See the Performance chapter of the users manual for information on preallocating matrices.
6030 
6031 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6032 @*/
6033 PetscErrorCode MatZeroEntries(Mat mat)
6034 {
6035   PetscFunctionBegin;
6036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6037   PetscValidType(mat, 1);
6038   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6039   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");
6040   MatCheckPreallocated(mat, 1);
6041 
6042   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6043   PetscUseTypeMethod(mat, zeroentries);
6044   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6045   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6046   PetscFunctionReturn(PETSC_SUCCESS);
6047 }
6048 
6049 /*@
6050    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6051    of a set of rows and columns of a matrix.
6052 
6053    Collective
6054 
6055    Input Parameters:
6056 +  mat - the matrix
6057 .  numRows - the number of rows/columns to zero
6058 .  rows - the global row indices
6059 .  diag - value put in the diagonal of the eliminated rows
6060 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6061 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6062 
6063    Level: intermediate
6064 
6065    Notes:
6066    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6067 
6068    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6069    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
6070 
6071    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6072    Krylov method to take advantage of the known solution on the zeroed rows.
6073 
6074    For the parallel case, all processes that share the matrix (i.e.,
6075    those in the communicator used for matrix creation) MUST call this
6076    routine, regardless of whether any rows being zeroed are owned by
6077    them.
6078 
6079    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6080 
6081    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6082    list only rows local to itself).
6083 
6084    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6085 
6086 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6087           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6088 @*/
6089 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6090 {
6091   PetscFunctionBegin;
6092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6093   PetscValidType(mat, 1);
6094   if (numRows) PetscValidIntPointer(rows, 3);
6095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6096   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6097   MatCheckPreallocated(mat, 1);
6098 
6099   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6100   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6101   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6102   PetscFunctionReturn(PETSC_SUCCESS);
6103 }
6104 
6105 /*@
6106    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6107    of a set of rows and columns of a matrix.
6108 
6109    Collective
6110 
6111    Input Parameters:
6112 +  mat - the matrix
6113 .  is - the rows to zero
6114 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6115 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6116 -  b - optional vector of right hand side, that will be adjusted by provided solution
6117 
6118    Level: intermediate
6119 
6120    Note:
6121    See `MatZeroRowsColumns()` for details on how this routine operates.
6122 
6123 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6124           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6125 @*/
6126 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6127 {
6128   PetscInt        numRows;
6129   const PetscInt *rows;
6130 
6131   PetscFunctionBegin;
6132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6133   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6134   PetscValidType(mat, 1);
6135   PetscValidType(is, 2);
6136   PetscCall(ISGetLocalSize(is, &numRows));
6137   PetscCall(ISGetIndices(is, &rows));
6138   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6139   PetscCall(ISRestoreIndices(is, &rows));
6140   PetscFunctionReturn(PETSC_SUCCESS);
6141 }
6142 
6143 /*@
6144    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6145    of a set of rows of a matrix.
6146 
6147    Collective
6148 
6149    Input Parameters:
6150 +  mat - the matrix
6151 .  numRows - the number of rows to zero
6152 .  rows - the global row indices
6153 .  diag - value put in the diagonal of the zeroed rows
6154 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6155 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6156 
6157    Level: intermediate
6158 
6159    Notes:
6160    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6161 
6162    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6163 
6164    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6165    Krylov method to take advantage of the known solution on the zeroed rows.
6166 
6167    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)
6168    from the matrix.
6169 
6170    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6171    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
6172    formats this does not alter the nonzero structure.
6173 
6174    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6175    of the matrix is not changed the values are
6176    merely zeroed.
6177 
6178    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6179    formats can optionally remove the main diagonal entry from the
6180    nonzero structure as well, by passing 0.0 as the final argument).
6181 
6182    For the parallel case, all processes that share the matrix (i.e.,
6183    those in the communicator used for matrix creation) MUST call this
6184    routine, regardless of whether any rows being zeroed are owned by
6185    them.
6186 
6187    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6188    list only rows local to itself).
6189 
6190    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6191    owns that are to be zeroed. This saves a global synchronization in the implementation.
6192 
6193 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6194           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6195 @*/
6196 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6197 {
6198   PetscFunctionBegin;
6199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6200   PetscValidType(mat, 1);
6201   if (numRows) PetscValidIntPointer(rows, 3);
6202   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6203   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6204   MatCheckPreallocated(mat, 1);
6205 
6206   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6207   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6208   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6209   PetscFunctionReturn(PETSC_SUCCESS);
6210 }
6211 
6212 /*@
6213    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6214    of a set of rows of a matrix.
6215 
6216    Collective
6217 
6218    Input Parameters:
6219 +  mat - the matrix
6220 .  is - index set of rows to remove (if `NULL` then no row is removed)
6221 .  diag - value put in all diagonals of eliminated rows
6222 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6223 -  b - optional vector of right hand side, that will be adjusted by provided solution
6224 
6225    Level: intermediate
6226 
6227    Note:
6228    See `MatZeroRows()` for details on how this routine operates.
6229 
6230 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6231           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6232 @*/
6233 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6234 {
6235   PetscInt        numRows = 0;
6236   const PetscInt *rows    = NULL;
6237 
6238   PetscFunctionBegin;
6239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6240   PetscValidType(mat, 1);
6241   if (is) {
6242     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6243     PetscCall(ISGetLocalSize(is, &numRows));
6244     PetscCall(ISGetIndices(is, &rows));
6245   }
6246   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6247   if (is) PetscCall(ISRestoreIndices(is, &rows));
6248   PetscFunctionReturn(PETSC_SUCCESS);
6249 }
6250 
6251 /*@
6252    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6253    of a set of rows of a matrix. These rows must be local to the process.
6254 
6255    Collective
6256 
6257    Input Parameters:
6258 +  mat - the matrix
6259 .  numRows - the number of rows to remove
6260 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6261 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6262 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6263 -  b - optional vector of right hand side, that will be adjusted by provided solution
6264 
6265    Level: intermediate
6266 
6267    Notes:
6268    See `MatZeroRows()` for details on how this routine operates.
6269 
6270    The grid coordinates are across the entire grid, not just the local portion
6271 
6272    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6273    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6274    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6275    `DM_BOUNDARY_PERIODIC` boundary type.
6276 
6277    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
6278    a single value per point) you can skip filling those indices.
6279 
6280    Fortran Note:
6281    `idxm` and `idxn` should be declared as
6282 $     MatStencil idxm(4,m)
6283    and the values inserted using
6284 .vb
6285     idxm(MatStencil_i,1) = i
6286     idxm(MatStencil_j,1) = j
6287     idxm(MatStencil_k,1) = k
6288     idxm(MatStencil_c,1) = c
6289    etc
6290 .ve
6291 
6292 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6293           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6294 @*/
6295 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6296 {
6297   PetscInt  dim    = mat->stencil.dim;
6298   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6299   PetscInt *dims   = mat->stencil.dims + 1;
6300   PetscInt *starts = mat->stencil.starts;
6301   PetscInt *dxm    = (PetscInt *)rows;
6302   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6303 
6304   PetscFunctionBegin;
6305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6306   PetscValidType(mat, 1);
6307   if (numRows) PetscValidPointer(rows, 3);
6308 
6309   PetscCall(PetscMalloc1(numRows, &jdxm));
6310   for (i = 0; i < numRows; ++i) {
6311     /* Skip unused dimensions (they are ordered k, j, i, c) */
6312     for (j = 0; j < 3 - sdim; ++j) dxm++;
6313     /* Local index in X dir */
6314     tmp = *dxm++ - starts[0];
6315     /* Loop over remaining dimensions */
6316     for (j = 0; j < dim - 1; ++j) {
6317       /* If nonlocal, set index to be negative */
6318       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6319       /* Update local index */
6320       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6321     }
6322     /* Skip component slot if necessary */
6323     if (mat->stencil.noc) dxm++;
6324     /* Local row number */
6325     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6326   }
6327   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6328   PetscCall(PetscFree(jdxm));
6329   PetscFunctionReturn(PETSC_SUCCESS);
6330 }
6331 
6332 /*@
6333    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6334    of a set of rows and columns of a matrix.
6335 
6336    Collective
6337 
6338    Input Parameters:
6339 +  mat - the matrix
6340 .  numRows - the number of rows/columns to remove
6341 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6342 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6343 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6344 -  b - optional vector of right hand side, that will be adjusted by provided solution
6345 
6346    Level: intermediate
6347 
6348    Notes:
6349    See `MatZeroRowsColumns()` for details on how this routine operates.
6350 
6351    The grid coordinates are across the entire grid, not just the local portion
6352 
6353    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6354    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6355    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6356    `DM_BOUNDARY_PERIODIC` boundary type.
6357 
6358    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
6359    a single value per point) you can skip filling those indices.
6360 
6361    Fortran Note:
6362    `idxm` and `idxn` should be declared as
6363 $     MatStencil idxm(4,m)
6364    and the values inserted using
6365 .vb
6366     idxm(MatStencil_i,1) = i
6367     idxm(MatStencil_j,1) = j
6368     idxm(MatStencil_k,1) = k
6369     idxm(MatStencil_c,1) = c
6370     etc
6371 .ve
6372 
6373 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6374           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6375 @*/
6376 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6377 {
6378   PetscInt  dim    = mat->stencil.dim;
6379   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6380   PetscInt *dims   = mat->stencil.dims + 1;
6381   PetscInt *starts = mat->stencil.starts;
6382   PetscInt *dxm    = (PetscInt *)rows;
6383   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6384 
6385   PetscFunctionBegin;
6386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6387   PetscValidType(mat, 1);
6388   if (numRows) PetscValidPointer(rows, 3);
6389 
6390   PetscCall(PetscMalloc1(numRows, &jdxm));
6391   for (i = 0; i < numRows; ++i) {
6392     /* Skip unused dimensions (they are ordered k, j, i, c) */
6393     for (j = 0; j < 3 - sdim; ++j) dxm++;
6394     /* Local index in X dir */
6395     tmp = *dxm++ - starts[0];
6396     /* Loop over remaining dimensions */
6397     for (j = 0; j < dim - 1; ++j) {
6398       /* If nonlocal, set index to be negative */
6399       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6400       /* Update local index */
6401       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6402     }
6403     /* Skip component slot if necessary */
6404     if (mat->stencil.noc) dxm++;
6405     /* Local row number */
6406     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6407   }
6408   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6409   PetscCall(PetscFree(jdxm));
6410   PetscFunctionReturn(PETSC_SUCCESS);
6411 }
6412 
6413 /*@C
6414    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6415    of a set of rows of a matrix; using local numbering of rows.
6416 
6417    Collective
6418 
6419    Input Parameters:
6420 +  mat - the matrix
6421 .  numRows - the number of rows to remove
6422 .  rows - the local row indices
6423 .  diag - value put in all diagonals of eliminated rows
6424 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6425 -  b - optional vector of right hand side, that will be adjusted by provided solution
6426 
6427    Level: intermediate
6428 
6429    Notes:
6430    Before calling `MatZeroRowsLocal()`, the user must first set the
6431    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6432 
6433    See `MatZeroRows()` for details on how this routine operates.
6434 
6435 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6436           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6437 @*/
6438 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6439 {
6440   PetscFunctionBegin;
6441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6442   PetscValidType(mat, 1);
6443   if (numRows) PetscValidIntPointer(rows, 3);
6444   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6445   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6446   MatCheckPreallocated(mat, 1);
6447 
6448   if (mat->ops->zerorowslocal) {
6449     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6450   } else {
6451     IS              is, newis;
6452     const PetscInt *newRows;
6453 
6454     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6455     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6456     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6457     PetscCall(ISGetIndices(newis, &newRows));
6458     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6459     PetscCall(ISRestoreIndices(newis, &newRows));
6460     PetscCall(ISDestroy(&newis));
6461     PetscCall(ISDestroy(&is));
6462   }
6463   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6464   PetscFunctionReturn(PETSC_SUCCESS);
6465 }
6466 
6467 /*@
6468    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6469    of a set of rows of a matrix; using local numbering of rows.
6470 
6471    Collective
6472 
6473    Input Parameters:
6474 +  mat - the matrix
6475 .  is - index set of rows to remove
6476 .  diag - value put in all diagonals of eliminated rows
6477 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6478 -  b - optional vector of right hand side, that will be adjusted by provided solution
6479 
6480    Level: intermediate
6481 
6482    Notes:
6483    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6484    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6485 
6486    See `MatZeroRows()` for details on how this routine operates.
6487 
6488 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6489           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6490 @*/
6491 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6492 {
6493   PetscInt        numRows;
6494   const PetscInt *rows;
6495 
6496   PetscFunctionBegin;
6497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6498   PetscValidType(mat, 1);
6499   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6500   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6501   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6502   MatCheckPreallocated(mat, 1);
6503 
6504   PetscCall(ISGetLocalSize(is, &numRows));
6505   PetscCall(ISGetIndices(is, &rows));
6506   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6507   PetscCall(ISRestoreIndices(is, &rows));
6508   PetscFunctionReturn(PETSC_SUCCESS);
6509 }
6510 
6511 /*@
6512    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6513    of a set of rows and columns of a matrix; using local numbering of rows.
6514 
6515    Collective
6516 
6517    Input Parameters:
6518 +  mat - the matrix
6519 .  numRows - the number of rows to remove
6520 .  rows - the global row indices
6521 .  diag - value put in all diagonals of eliminated rows
6522 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6523 -  b - optional vector of right hand side, that will be adjusted by provided solution
6524 
6525    Level: intermediate
6526 
6527    Notes:
6528    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6529    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6530 
6531    See `MatZeroRowsColumns()` for details on how this routine operates.
6532 
6533 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6534           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6535 @*/
6536 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6537 {
6538   IS              is, newis;
6539   const PetscInt *newRows;
6540 
6541   PetscFunctionBegin;
6542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6543   PetscValidType(mat, 1);
6544   if (numRows) PetscValidIntPointer(rows, 3);
6545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6547   MatCheckPreallocated(mat, 1);
6548 
6549   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6550   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6551   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6552   PetscCall(ISGetIndices(newis, &newRows));
6553   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6554   PetscCall(ISRestoreIndices(newis, &newRows));
6555   PetscCall(ISDestroy(&newis));
6556   PetscCall(ISDestroy(&is));
6557   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6558   PetscFunctionReturn(PETSC_SUCCESS);
6559 }
6560 
6561 /*@
6562    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6563    of a set of rows and columns of a matrix; using local numbering of rows.
6564 
6565    Collective
6566 
6567    Input Parameters:
6568 +  mat - the matrix
6569 .  is - index set of rows to remove
6570 .  diag - value put in all diagonals of eliminated rows
6571 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6572 -  b - optional vector of right hand side, that will be adjusted by provided solution
6573 
6574    Level: intermediate
6575 
6576    Notes:
6577    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6578    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6579 
6580    See `MatZeroRowsColumns()` for details on how this routine operates.
6581 
6582 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6583           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6584 @*/
6585 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6586 {
6587   PetscInt        numRows;
6588   const PetscInt *rows;
6589 
6590   PetscFunctionBegin;
6591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6592   PetscValidType(mat, 1);
6593   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6595   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6596   MatCheckPreallocated(mat, 1);
6597 
6598   PetscCall(ISGetLocalSize(is, &numRows));
6599   PetscCall(ISGetIndices(is, &rows));
6600   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6601   PetscCall(ISRestoreIndices(is, &rows));
6602   PetscFunctionReturn(PETSC_SUCCESS);
6603 }
6604 
6605 /*@C
6606    MatGetSize - Returns the numbers of rows and columns in a matrix.
6607 
6608    Not Collective
6609 
6610    Input Parameter:
6611 .  mat - the matrix
6612 
6613    Output Parameters:
6614 +  m - the number of global rows
6615 -  n - the number of global columns
6616 
6617    Level: beginner
6618 
6619    Note:
6620    Both output parameters can be `NULL` on input.
6621 
6622 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6623 @*/
6624 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6625 {
6626   PetscFunctionBegin;
6627   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6628   if (m) *m = mat->rmap->N;
6629   if (n) *n = mat->cmap->N;
6630   PetscFunctionReturn(PETSC_SUCCESS);
6631 }
6632 
6633 /*@C
6634    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6635    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6636 
6637    Not Collective
6638 
6639    Input Parameter:
6640 .  mat - the matrix
6641 
6642    Output Parameters:
6643 +  m - the number of local rows, use `NULL` to not obtain this value
6644 -  n - the number of local columns, use `NULL` to not obtain this value
6645 
6646    Level: beginner
6647 
6648 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6649 @*/
6650 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6651 {
6652   PetscFunctionBegin;
6653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6654   if (m) PetscValidIntPointer(m, 2);
6655   if (n) PetscValidIntPointer(n, 3);
6656   if (m) *m = mat->rmap->n;
6657   if (n) *n = mat->cmap->n;
6658   PetscFunctionReturn(PETSC_SUCCESS);
6659 }
6660 
6661 /*@C
6662    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6663    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6664 
6665    Not Collective, unless matrix has not been allocated, then collective
6666 
6667    Input Parameter:
6668 .  mat - the matrix
6669 
6670    Output Parameters:
6671 +  m - the global index of the first local column, use `NULL` to not obtain this value
6672 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6673 
6674    Level: developer
6675 
6676 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6677 @*/
6678 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6679 {
6680   PetscFunctionBegin;
6681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6682   PetscValidType(mat, 1);
6683   if (m) PetscValidIntPointer(m, 2);
6684   if (n) PetscValidIntPointer(n, 3);
6685   MatCheckPreallocated(mat, 1);
6686   if (m) *m = mat->cmap->rstart;
6687   if (n) *n = mat->cmap->rend;
6688   PetscFunctionReturn(PETSC_SUCCESS);
6689 }
6690 
6691 /*@C
6692    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6693    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
6694    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6695 
6696    Not Collective
6697 
6698    Input Parameter:
6699 .  mat - the matrix
6700 
6701    Output Parameters:
6702 +  m - the global index of the first local row, use `NULL` to not obtain this value
6703 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6704 
6705    Level: beginner
6706 
6707    Note:
6708   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6709   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6710   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6711 
6712 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6713           `PetscLayout`
6714 @*/
6715 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6716 {
6717   PetscFunctionBegin;
6718   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6719   PetscValidType(mat, 1);
6720   if (m) PetscValidIntPointer(m, 2);
6721   if (n) PetscValidIntPointer(n, 3);
6722   MatCheckPreallocated(mat, 1);
6723   if (m) *m = mat->rmap->rstart;
6724   if (n) *n = mat->rmap->rend;
6725   PetscFunctionReturn(PETSC_SUCCESS);
6726 }
6727 
6728 /*@C
6729    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6730    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
6731    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6732 
6733    Not Collective, unless matrix has not been allocated
6734 
6735    Input Parameter:
6736 .  mat - the matrix
6737 
6738    Output Parameter:
6739 .  ranges - start of each processors portion plus one more than the total length at the end
6740 
6741    Level: beginner
6742 
6743 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6744 @*/
6745 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6746 {
6747   PetscFunctionBegin;
6748   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6749   PetscValidType(mat, 1);
6750   MatCheckPreallocated(mat, 1);
6751   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6752   PetscFunctionReturn(PETSC_SUCCESS);
6753 }
6754 
6755 /*@C
6756    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6757    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6758 
6759    Not Collective, unless matrix has not been allocated
6760 
6761    Input Parameter:
6762 .  mat - the matrix
6763 
6764    Output Parameter:
6765 .  ranges - start of each processors portion plus one more then the total length at the end
6766 
6767    Level: beginner
6768 
6769 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6770 @*/
6771 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6772 {
6773   PetscFunctionBegin;
6774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6775   PetscValidType(mat, 1);
6776   MatCheckPreallocated(mat, 1);
6777   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6778   PetscFunctionReturn(PETSC_SUCCESS);
6779 }
6780 
6781 /*@C
6782    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6783    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6784    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6785 
6786    Not Collective
6787 
6788    Input Parameter:
6789 .  A - matrix
6790 
6791    Output Parameters:
6792 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6793 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6794 
6795    Level: intermediate
6796 
6797 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6798 @*/
6799 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6800 {
6801   PetscErrorCode (*f)(Mat, IS *, IS *);
6802 
6803   PetscFunctionBegin;
6804   MatCheckPreallocated(A, 1);
6805   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6806   if (f) {
6807     PetscCall((*f)(A, rows, cols));
6808   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6809     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6810     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6811   }
6812   PetscFunctionReturn(PETSC_SUCCESS);
6813 }
6814 
6815 /*@C
6816    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6817    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6818    to complete the factorization.
6819 
6820    Collective
6821 
6822    Input Parameters:
6823 +  fact - the factorized matrix obtained with `MatGetFactor()`
6824 .  mat - the matrix
6825 .  row - row permutation
6826 .  col - column permutation
6827 -  info - structure containing
6828 .vb
6829       levels - number of levels of fill.
6830       expected fill - as ratio of original fill.
6831       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6832                 missing diagonal entries)
6833 .ve
6834 
6835    Level: developer
6836 
6837    Notes:
6838    See [Matrix Factorization](sec_matfactor) for additional information.
6839 
6840    Most users should employ the `KSP` interface for linear solvers
6841    instead of working directly with matrix algebra routines such as this.
6842    See, e.g., `KSPCreate()`.
6843 
6844    Uses the definition of level of fill as in Y. Saad, 2003
6845 
6846    Developer Note:
6847    The Fortran interface is not autogenerated as the
6848    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6849 
6850    References:
6851 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6852 
6853 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6854           `MatGetOrdering()`, `MatFactorInfo`
6855 @*/
6856 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6857 {
6858   PetscFunctionBegin;
6859   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6860   PetscValidType(mat, 2);
6861   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6862   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6863   PetscValidPointer(info, 5);
6864   PetscValidPointer(fact, 1);
6865   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6866   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6867   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6869   MatCheckPreallocated(mat, 2);
6870 
6871   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6872   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6873   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6874   PetscFunctionReturn(PETSC_SUCCESS);
6875 }
6876 
6877 /*@C
6878    MatICCFactorSymbolic - Performs symbolic incomplete
6879    Cholesky factorization for a symmetric matrix.  Use
6880    `MatCholeskyFactorNumeric()` to complete the factorization.
6881 
6882    Collective
6883 
6884    Input Parameters:
6885 +  fact - the factorized matrix obtained with `MatGetFactor()`
6886 .  mat - the matrix to be factored
6887 .  perm - row and column permutation
6888 -  info - structure containing
6889 .vb
6890       levels - number of levels of fill.
6891       expected fill - as ratio of original fill.
6892 .ve
6893 
6894    Level: developer
6895 
6896    Notes:
6897    Most users should employ the `KSP` interface for linear solvers
6898    instead of working directly with matrix algebra routines such as this.
6899    See, e.g., `KSPCreate()`.
6900 
6901    This uses the definition of level of fill as in Y. Saad, 2003
6902 
6903    Developer Note:
6904    The Fortran interface is not autogenerated as the
6905    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6906 
6907    References:
6908 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6909 
6910 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6911 @*/
6912 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6913 {
6914   PetscFunctionBegin;
6915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6916   PetscValidType(mat, 2);
6917   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6918   PetscValidPointer(info, 4);
6919   PetscValidPointer(fact, 1);
6920   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6921   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6922   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6923   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6924   MatCheckPreallocated(mat, 2);
6925 
6926   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6927   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6928   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6929   PetscFunctionReturn(PETSC_SUCCESS);
6930 }
6931 
6932 /*@C
6933    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6934    points to an array of valid matrices, they may be reused to store the new
6935    submatrices.
6936 
6937    Collective
6938 
6939    Input Parameters:
6940 +  mat - the matrix
6941 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6942 .  irow - index set of rows to extract
6943 .  icol - index set of columns to extract
6944 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6945 
6946    Output Parameter:
6947 .  submat - the array of submatrices
6948 
6949    Level: advanced
6950 
6951    Notes:
6952    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6953    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6954    to extract a parallel submatrix.
6955 
6956    Some matrix types place restrictions on the row and column
6957    indices, such as that they be sorted or that they be equal to each other.
6958 
6959    The index sets may not have duplicate entries.
6960 
6961    When extracting submatrices from a parallel matrix, each processor can
6962    form a different submatrix by setting the rows and columns of its
6963    individual index sets according to the local submatrix desired.
6964 
6965    When finished using the submatrices, the user should destroy
6966    them with `MatDestroySubMatrices()`.
6967 
6968    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6969    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6970 
6971    This routine creates the matrices in submat; you should NOT create them before
6972    calling it. It also allocates the array of matrix pointers submat.
6973 
6974    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6975    request one row/column in a block, they must request all rows/columns that are in
6976    that block. For example, if the block size is 2 you cannot request just row 0 and
6977    column 0.
6978 
6979    Fortran Note:
6980    The Fortran interface is slightly different from that given below; it
6981    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6982 
6983 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6984 @*/
6985 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6986 {
6987   PetscInt  i;
6988   PetscBool eq;
6989 
6990   PetscFunctionBegin;
6991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6992   PetscValidType(mat, 1);
6993   if (n) {
6994     PetscValidPointer(irow, 3);
6995     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6996     PetscValidPointer(icol, 4);
6997     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6998   }
6999   PetscValidPointer(submat, 6);
7000   if (n && scall == MAT_REUSE_MATRIX) {
7001     PetscValidPointer(*submat, 6);
7002     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7003   }
7004   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7005   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7006   MatCheckPreallocated(mat, 1);
7007   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7008   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7009   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7010   for (i = 0; i < n; i++) {
7011     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7012     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7013     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7014 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7015     if (mat->boundtocpu && mat->bindingpropagates) {
7016       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7017       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7018     }
7019 #endif
7020   }
7021   PetscFunctionReturn(PETSC_SUCCESS);
7022 }
7023 
7024 /*@C
7025    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7026 
7027    Collective
7028 
7029    Input Parameters:
7030 +  mat - the matrix
7031 .  n   - the number of submatrixes to be extracted
7032 .  irow - index set of rows to extract
7033 .  icol - index set of columns to extract
7034 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7035 
7036    Output Parameter:
7037 .  submat - the array of submatrices
7038 
7039    Level: advanced
7040 
7041    Note:
7042    This is used by `PCGASM`
7043 
7044 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7045 @*/
7046 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7047 {
7048   PetscInt  i;
7049   PetscBool eq;
7050 
7051   PetscFunctionBegin;
7052   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7053   PetscValidType(mat, 1);
7054   if (n) {
7055     PetscValidPointer(irow, 3);
7056     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7057     PetscValidPointer(icol, 4);
7058     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7059   }
7060   PetscValidPointer(submat, 6);
7061   if (n && scall == MAT_REUSE_MATRIX) {
7062     PetscValidPointer(*submat, 6);
7063     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7064   }
7065   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7066   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7067   MatCheckPreallocated(mat, 1);
7068 
7069   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7070   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7071   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7072   for (i = 0; i < n; i++) {
7073     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7074     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7075   }
7076   PetscFunctionReturn(PETSC_SUCCESS);
7077 }
7078 
7079 /*@C
7080    MatDestroyMatrices - Destroys an array of matrices.
7081 
7082    Collective
7083 
7084    Input Parameters:
7085 +  n - the number of local matrices
7086 -  mat - the matrices (this is a pointer to the array of matrices)
7087 
7088    Level: advanced
7089 
7090     Note:
7091     Frees not only the matrices, but also the array that contains the matrices
7092 
7093     Fortran Note:
7094     This does not free the array.
7095 
7096 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7097 @*/
7098 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7099 {
7100   PetscInt i;
7101 
7102   PetscFunctionBegin;
7103   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7104   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7105   PetscValidPointer(mat, 2);
7106 
7107   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7108 
7109   /* memory is allocated even if n = 0 */
7110   PetscCall(PetscFree(*mat));
7111   PetscFunctionReturn(PETSC_SUCCESS);
7112 }
7113 
7114 /*@C
7115    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7116 
7117    Collective
7118 
7119    Input Parameters:
7120 +  n - the number of local matrices
7121 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7122                        sequence of `MatCreateSubMatrices()`)
7123 
7124    Level: advanced
7125 
7126     Note:
7127     Frees not only the matrices, but also the array that contains the matrices
7128 
7129     Fortran Note:
7130     This does not free the array.
7131 
7132 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7133 @*/
7134 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7135 {
7136   Mat mat0;
7137 
7138   PetscFunctionBegin;
7139   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7140   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7141   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7142   PetscValidPointer(mat, 2);
7143 
7144   mat0 = (*mat)[0];
7145   if (mat0 && mat0->ops->destroysubmatrices) {
7146     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7147   } else {
7148     PetscCall(MatDestroyMatrices(n, mat));
7149   }
7150   PetscFunctionReturn(PETSC_SUCCESS);
7151 }
7152 
7153 /*@C
7154    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7155 
7156    Collective
7157 
7158    Input Parameter:
7159 .  mat - the matrix
7160 
7161    Output Parameter:
7162 .  matstruct - the sequential matrix with the nonzero structure of mat
7163 
7164   Level: developer
7165 
7166 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7167 @*/
7168 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7169 {
7170   PetscFunctionBegin;
7171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7172   PetscValidPointer(matstruct, 2);
7173 
7174   PetscValidType(mat, 1);
7175   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7176   MatCheckPreallocated(mat, 1);
7177 
7178   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7179   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7180   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7181   PetscFunctionReturn(PETSC_SUCCESS);
7182 }
7183 
7184 /*@C
7185    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7186 
7187    Collective
7188 
7189    Input Parameter:
7190 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7191                        sequence of `MatGetSeqNonzeroStructure()`)
7192 
7193    Level: advanced
7194 
7195     Note:
7196     Frees not only the matrices, but also the array that contains the matrices
7197 
7198 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7199 @*/
7200 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7201 {
7202   PetscFunctionBegin;
7203   PetscValidPointer(mat, 1);
7204   PetscCall(MatDestroy(mat));
7205   PetscFunctionReturn(PETSC_SUCCESS);
7206 }
7207 
7208 /*@
7209    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7210    replaces the index sets by larger ones that represent submatrices with
7211    additional overlap.
7212 
7213    Collective
7214 
7215    Input Parameters:
7216 +  mat - the matrix
7217 .  n   - the number of index sets
7218 .  is  - the array of index sets (these index sets will changed during the call)
7219 -  ov  - the additional overlap requested
7220 
7221    Options Database Key:
7222 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7223 
7224    Level: developer
7225 
7226    Note:
7227    The computed overlap preserves the matrix block sizes when the blocks are square.
7228    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7229    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7230 
7231 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7232 @*/
7233 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7234 {
7235   PetscInt i, bs, cbs;
7236 
7237   PetscFunctionBegin;
7238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7239   PetscValidType(mat, 1);
7240   PetscValidLogicalCollectiveInt(mat, n, 2);
7241   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7242   if (n) {
7243     PetscValidPointer(is, 3);
7244     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7245   }
7246   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7247   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7248   MatCheckPreallocated(mat, 1);
7249 
7250   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7251   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7252   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7253   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7254   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7255   if (bs == cbs) {
7256     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7257   }
7258   PetscFunctionReturn(PETSC_SUCCESS);
7259 }
7260 
7261 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7262 
7263 /*@
7264    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7265    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7266    additional overlap.
7267 
7268    Collective
7269 
7270    Input Parameters:
7271 +  mat - the matrix
7272 .  n   - the number of index sets
7273 .  is  - the array of index sets (these index sets will changed during the call)
7274 -  ov  - the additional overlap requested
7275 
7276 `   Options Database Key:
7277 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7278 
7279    Level: developer
7280 
7281 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7282 @*/
7283 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7284 {
7285   PetscInt i;
7286 
7287   PetscFunctionBegin;
7288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7289   PetscValidType(mat, 1);
7290   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7291   if (n) {
7292     PetscValidPointer(is, 3);
7293     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7294   }
7295   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7296   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7297   MatCheckPreallocated(mat, 1);
7298   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7299   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7300   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7301   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7302   PetscFunctionReturn(PETSC_SUCCESS);
7303 }
7304 
7305 /*@
7306    MatGetBlockSize - Returns the matrix block size.
7307 
7308    Not Collective
7309 
7310    Input Parameter:
7311 .  mat - the matrix
7312 
7313    Output Parameter:
7314 .  bs - block size
7315 
7316    Level: intermediate
7317 
7318    Notes:
7319     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7320 
7321    If the block size has not been set yet this routine returns 1.
7322 
7323 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7324 @*/
7325 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7326 {
7327   PetscFunctionBegin;
7328   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7329   PetscValidIntPointer(bs, 2);
7330   *bs = PetscAbs(mat->rmap->bs);
7331   PetscFunctionReturn(PETSC_SUCCESS);
7332 }
7333 
7334 /*@
7335    MatGetBlockSizes - Returns the matrix block row and column sizes.
7336 
7337    Not Collective
7338 
7339    Input Parameter:
7340 .  mat - the matrix
7341 
7342    Output Parameters:
7343 +  rbs - row block size
7344 -  cbs - column block size
7345 
7346    Level: intermediate
7347 
7348    Notes:
7349     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7350     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7351 
7352    If a block size has not been set yet this routine returns 1.
7353 
7354 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7355 @*/
7356 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7357 {
7358   PetscFunctionBegin;
7359   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7360   if (rbs) PetscValidIntPointer(rbs, 2);
7361   if (cbs) PetscValidIntPointer(cbs, 3);
7362   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7363   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7364   PetscFunctionReturn(PETSC_SUCCESS);
7365 }
7366 
7367 /*@
7368    MatSetBlockSize - Sets the matrix block size.
7369 
7370    Logically Collective
7371 
7372    Input Parameters:
7373 +  mat - the matrix
7374 -  bs - block size
7375 
7376    Level: intermediate
7377 
7378    Notes:
7379     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7380     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7381 
7382     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7383     is compatible with the matrix local sizes.
7384 
7385 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7386 @*/
7387 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7388 {
7389   PetscFunctionBegin;
7390   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7391   PetscValidLogicalCollectiveInt(mat, bs, 2);
7392   PetscCall(MatSetBlockSizes(mat, bs, bs));
7393   PetscFunctionReturn(PETSC_SUCCESS);
7394 }
7395 
7396 typedef struct {
7397   PetscInt         n;
7398   IS              *is;
7399   Mat             *mat;
7400   PetscObjectState nonzerostate;
7401   Mat              C;
7402 } EnvelopeData;
7403 
7404 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7405 {
7406   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7407   PetscCall(PetscFree(edata->is));
7408   PetscCall(PetscFree(edata));
7409   return PETSC_SUCCESS;
7410 }
7411 
7412 /*
7413    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7414          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7415 
7416    Collective
7417 
7418    Input Parameter:
7419 .  mat - the matrix
7420 
7421    Notes:
7422      There can be zeros within the blocks
7423 
7424      The blocks can overlap between processes, including laying on more than two processes
7425 
7426 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7427 */
7428 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7429 {
7430   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7431   PetscInt          *diag, *odiag, sc;
7432   VecScatter         scatter;
7433   PetscScalar       *seqv;
7434   const PetscScalar *parv;
7435   const PetscInt    *ia, *ja;
7436   PetscBool          set, flag, done;
7437   Mat                AA = mat, A;
7438   MPI_Comm           comm;
7439   PetscMPIInt        rank, size, tag;
7440   MPI_Status         status;
7441   PetscContainer     container;
7442   EnvelopeData      *edata;
7443   Vec                seq, par;
7444   IS                 isglobal;
7445 
7446   PetscFunctionBegin;
7447   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7448   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7449   if (!set || !flag) {
7450     /* TOO: only needs nonzero structure of transpose */
7451     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7452     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7453   }
7454   PetscCall(MatAIJGetLocalMat(AA, &A));
7455   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7456   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7457 
7458   PetscCall(MatGetLocalSize(mat, &n, NULL));
7459   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7460   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7461   PetscCallMPI(MPI_Comm_size(comm, &size));
7462   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7463 
7464   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7465 
7466   if (rank > 0) {
7467     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7468     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7469   }
7470   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7471   for (i = 0; i < n; i++) {
7472     env = PetscMax(env, ja[ia[i + 1] - 1]);
7473     II  = rstart + i;
7474     if (env == II) {
7475       starts[lblocks]  = tbs;
7476       sizes[lblocks++] = 1 + II - tbs;
7477       tbs              = 1 + II;
7478     }
7479   }
7480   if (rank < size - 1) {
7481     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7482     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7483   }
7484 
7485   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7486   if (!set || !flag) PetscCall(MatDestroy(&AA));
7487   PetscCall(MatDestroy(&A));
7488 
7489   PetscCall(PetscNew(&edata));
7490   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7491   edata->n = lblocks;
7492   /* create IS needed for extracting blocks from the original matrix */
7493   PetscCall(PetscMalloc1(lblocks, &edata->is));
7494   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7495 
7496   /* Create the resulting inverse matrix structure with preallocation information */
7497   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7498   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7499   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7500   PetscCall(MatSetType(edata->C, MATAIJ));
7501 
7502   /* Communicate the start and end of each row, from each block to the correct rank */
7503   /* TODO: Use PetscSF instead of VecScatter */
7504   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7505   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7506   PetscCall(VecGetArrayWrite(seq, &seqv));
7507   for (PetscInt i = 0; i < lblocks; i++) {
7508     for (PetscInt j = 0; j < sizes[i]; j++) {
7509       seqv[cnt]     = starts[i];
7510       seqv[cnt + 1] = starts[i] + sizes[i];
7511       cnt += 2;
7512     }
7513   }
7514   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7515   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7516   sc -= cnt;
7517   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7518   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7519   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7520   PetscCall(ISDestroy(&isglobal));
7521   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7522   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7523   PetscCall(VecScatterDestroy(&scatter));
7524   PetscCall(VecDestroy(&seq));
7525   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7526   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7527   PetscCall(VecGetArrayRead(par, &parv));
7528   cnt = 0;
7529   PetscCall(MatGetSize(mat, NULL, &n));
7530   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7531     PetscInt start, end, d = 0, od = 0;
7532 
7533     start = (PetscInt)PetscRealPart(parv[cnt]);
7534     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7535     cnt += 2;
7536 
7537     if (start < cstart) {
7538       od += cstart - start + n - cend;
7539       d += cend - cstart;
7540     } else if (start < cend) {
7541       od += n - cend;
7542       d += cend - start;
7543     } else od += n - start;
7544     if (end <= cstart) {
7545       od -= cstart - end + n - cend;
7546       d -= cend - cstart;
7547     } else if (end < cend) {
7548       od -= n - cend;
7549       d -= cend - end;
7550     } else od -= n - end;
7551 
7552     odiag[i] = od;
7553     diag[i]  = d;
7554   }
7555   PetscCall(VecRestoreArrayRead(par, &parv));
7556   PetscCall(VecDestroy(&par));
7557   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7558   PetscCall(PetscFree2(diag, odiag));
7559   PetscCall(PetscFree2(sizes, starts));
7560 
7561   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7562   PetscCall(PetscContainerSetPointer(container, edata));
7563   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7564   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7565   PetscCall(PetscObjectDereference((PetscObject)container));
7566   PetscFunctionReturn(PETSC_SUCCESS);
7567 }
7568 
7569 /*@
7570   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7571 
7572   Collective
7573 
7574   Input Parameters:
7575 + A - the matrix
7576 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7577 
7578   Output Parameter:
7579 . C - matrix with inverted block diagonal of `A`
7580 
7581   Level: advanced
7582 
7583   Note:
7584      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7585 
7586 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7587 @*/
7588 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7589 {
7590   PetscContainer   container;
7591   EnvelopeData    *edata;
7592   PetscObjectState nonzerostate;
7593 
7594   PetscFunctionBegin;
7595   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7596   if (!container) {
7597     PetscCall(MatComputeVariableBlockEnvelope(A));
7598     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7599   }
7600   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7601   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7602   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7603   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7604 
7605   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7606   *C = edata->C;
7607 
7608   for (PetscInt i = 0; i < edata->n; i++) {
7609     Mat          D;
7610     PetscScalar *dvalues;
7611 
7612     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7613     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7614     PetscCall(MatSeqDenseInvert(D));
7615     PetscCall(MatDenseGetArray(D, &dvalues));
7616     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7617     PetscCall(MatDestroy(&D));
7618   }
7619   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7620   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7621   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7622   PetscFunctionReturn(PETSC_SUCCESS);
7623 }
7624 
7625 /*@
7626    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7627 
7628    Logically Collective
7629 
7630    Input Parameters:
7631 +  mat - the matrix
7632 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7633 -  bsizes - the block sizes
7634 
7635    Level: intermediate
7636 
7637    Notes:
7638     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7639 
7640     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.
7641 
7642 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7643           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7644 @*/
7645 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7646 {
7647   PetscInt i, ncnt = 0, nlocal;
7648 
7649   PetscFunctionBegin;
7650   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7651   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7652   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7653   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7654   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);
7655   PetscCall(PetscFree(mat->bsizes));
7656   mat->nblocks = nblocks;
7657   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7658   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7659   PetscFunctionReturn(PETSC_SUCCESS);
7660 }
7661 
7662 /*@C
7663    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7664 
7665    Logically Collective; No Fortran Support
7666 
7667    Input Parameter:
7668 .  mat - the matrix
7669 
7670    Output Parameters:
7671 +  nblocks - the number of blocks on this process
7672 -  bsizes - the block sizes
7673 
7674    Level: intermediate
7675 
7676 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7677 @*/
7678 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7679 {
7680   PetscFunctionBegin;
7681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7682   *nblocks = mat->nblocks;
7683   *bsizes  = mat->bsizes;
7684   PetscFunctionReturn(PETSC_SUCCESS);
7685 }
7686 
7687 /*@
7688    MatSetBlockSizes - Sets the matrix block row and column sizes.
7689 
7690    Logically Collective
7691 
7692    Input Parameters:
7693 +  mat - the matrix
7694 .  rbs - row block size
7695 -  cbs - column block size
7696 
7697    Level: intermediate
7698 
7699    Notes:
7700     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7701     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7702     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7703 
7704     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7705     are compatible with the matrix local sizes.
7706 
7707     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7708 
7709 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7710 @*/
7711 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7712 {
7713   PetscFunctionBegin;
7714   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7715   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7716   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7717   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7718   if (mat->rmap->refcnt) {
7719     ISLocalToGlobalMapping l2g  = NULL;
7720     PetscLayout            nmap = NULL;
7721 
7722     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7723     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7724     PetscCall(PetscLayoutDestroy(&mat->rmap));
7725     mat->rmap          = nmap;
7726     mat->rmap->mapping = l2g;
7727   }
7728   if (mat->cmap->refcnt) {
7729     ISLocalToGlobalMapping l2g  = NULL;
7730     PetscLayout            nmap = NULL;
7731 
7732     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7733     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7734     PetscCall(PetscLayoutDestroy(&mat->cmap));
7735     mat->cmap          = nmap;
7736     mat->cmap->mapping = l2g;
7737   }
7738   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7739   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7740   PetscFunctionReturn(PETSC_SUCCESS);
7741 }
7742 
7743 /*@
7744    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7745 
7746    Logically Collective
7747 
7748    Input Parameters:
7749 +  mat - the matrix
7750 .  fromRow - matrix from which to copy row block size
7751 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7752 
7753    Level: developer
7754 
7755 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7756 @*/
7757 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7758 {
7759   PetscFunctionBegin;
7760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7761   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7762   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7763   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7764   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7765   PetscFunctionReturn(PETSC_SUCCESS);
7766 }
7767 
7768 /*@
7769    MatResidual - Default routine to calculate the residual r = b - Ax
7770 
7771    Collective
7772 
7773    Input Parameters:
7774 +  mat - the matrix
7775 .  b   - the right-hand-side
7776 -  x   - the approximate solution
7777 
7778    Output Parameter:
7779 .  r - location to store the residual
7780 
7781    Level: developer
7782 
7783 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7784 @*/
7785 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7786 {
7787   PetscFunctionBegin;
7788   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7789   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7790   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7791   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7792   PetscValidType(mat, 1);
7793   MatCheckPreallocated(mat, 1);
7794   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7795   if (!mat->ops->residual) {
7796     PetscCall(MatMult(mat, x, r));
7797     PetscCall(VecAYPX(r, -1.0, b));
7798   } else {
7799     PetscUseTypeMethod(mat, residual, b, x, r);
7800   }
7801   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7802   PetscFunctionReturn(PETSC_SUCCESS);
7803 }
7804 
7805 /*MC
7806     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7807 
7808     Synopsis:
7809     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7810 
7811     Not Collective
7812 
7813     Input Parameters:
7814 +   A - the matrix
7815 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7816 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7817 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7818                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7819                  always used.
7820 
7821     Output Parameters:
7822 +   n - number of local rows in the (possibly compressed) matrix
7823 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7824 .   ja - the column indices
7825 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7826            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7827 
7828     Level: developer
7829 
7830     Note:
7831     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7832 
7833 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7834 M*/
7835 
7836 /*MC
7837     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7838 
7839     Synopsis:
7840     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7841 
7842     Not Collective
7843 
7844     Input Parameters:
7845 +   A - the  matrix
7846 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7847 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7848     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7849                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7850                  always used.
7851 .   n - number of local rows in the (possibly compressed) matrix
7852 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7853 .   ja - the column indices
7854 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7855            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7856 
7857     Level: developer
7858 
7859 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7860 M*/
7861 
7862 /*@C
7863     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7864 
7865    Collective
7866 
7867     Input Parameters:
7868 +   mat - the matrix
7869 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7870 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7871 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7872                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7873                  always used.
7874 
7875     Output Parameters:
7876 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7877 .   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
7878 .   ja - the column indices, use `NULL` if not needed
7879 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7880            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7881 
7882     Level: developer
7883 
7884     Notes:
7885     You CANNOT change any of the ia[] or ja[] values.
7886 
7887     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7888 
7889     Fortran Notes:
7890     Use
7891 .vb
7892     PetscInt, pointer :: ia(:),ja(:)
7893     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7894     ! Access the ith and jth entries via ia(i) and ja(j)
7895 .ve
7896    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7897 
7898 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7899 @*/
7900 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7901 {
7902   PetscFunctionBegin;
7903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7904   PetscValidType(mat, 1);
7905   if (n) PetscValidIntPointer(n, 5);
7906   if (ia) PetscValidPointer(ia, 6);
7907   if (ja) PetscValidPointer(ja, 7);
7908   if (done) PetscValidBoolPointer(done, 8);
7909   MatCheckPreallocated(mat, 1);
7910   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7911   else {
7912     if (done) *done = PETSC_TRUE;
7913     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7914     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7915     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7916   }
7917   PetscFunctionReturn(PETSC_SUCCESS);
7918 }
7919 
7920 /*@C
7921     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7922 
7923     Collective
7924 
7925     Input Parameters:
7926 +   mat - the matrix
7927 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7928 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7929                 symmetrized
7930 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7931                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7932                  always used.
7933 .   n - number of columns in the (possibly compressed) matrix
7934 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7935 -   ja - the row indices
7936 
7937     Output Parameter:
7938 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7939 
7940     Level: developer
7941 
7942 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7943 @*/
7944 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7945 {
7946   PetscFunctionBegin;
7947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7948   PetscValidType(mat, 1);
7949   PetscValidIntPointer(n, 5);
7950   if (ia) PetscValidPointer(ia, 6);
7951   if (ja) PetscValidPointer(ja, 7);
7952   PetscValidBoolPointer(done, 8);
7953   MatCheckPreallocated(mat, 1);
7954   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7955   else {
7956     *done = PETSC_TRUE;
7957     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7958   }
7959   PetscFunctionReturn(PETSC_SUCCESS);
7960 }
7961 
7962 /*@C
7963     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7964 
7965     Collective
7966 
7967     Input Parameters:
7968 +   mat - the matrix
7969 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7970 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7971 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7972                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7973                  always used.
7974 .   n - size of (possibly compressed) matrix
7975 .   ia - the row pointers
7976 -   ja - the column indices
7977 
7978     Output Parameter:
7979 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7980 
7981     Level: developer
7982 
7983     Note:
7984     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7985     us of the array after it has been restored. If you pass `NULL`, it will
7986     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7987 
7988     Fortran Note:
7989    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7990 
7991 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7992 @*/
7993 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7994 {
7995   PetscFunctionBegin;
7996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7997   PetscValidType(mat, 1);
7998   if (ia) PetscValidPointer(ia, 6);
7999   if (ja) PetscValidPointer(ja, 7);
8000   if (done) PetscValidBoolPointer(done, 8);
8001   MatCheckPreallocated(mat, 1);
8002 
8003   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8004   else {
8005     if (done) *done = PETSC_TRUE;
8006     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8007     if (n) *n = 0;
8008     if (ia) *ia = NULL;
8009     if (ja) *ja = NULL;
8010   }
8011   PetscFunctionReturn(PETSC_SUCCESS);
8012 }
8013 
8014 /*@C
8015     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8016 
8017     Collective
8018 
8019     Input Parameters:
8020 +   mat - the matrix
8021 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8022 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8023 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8024                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8025                  always used.
8026 
8027     Output Parameters:
8028 +   n - size of (possibly compressed) matrix
8029 .   ia - the column pointers
8030 .   ja - the row indices
8031 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8032 
8033     Level: developer
8034 
8035 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8036 @*/
8037 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8038 {
8039   PetscFunctionBegin;
8040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8041   PetscValidType(mat, 1);
8042   if (ia) PetscValidPointer(ia, 6);
8043   if (ja) PetscValidPointer(ja, 7);
8044   PetscValidBoolPointer(done, 8);
8045   MatCheckPreallocated(mat, 1);
8046 
8047   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8048   else {
8049     *done = PETSC_TRUE;
8050     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8051     if (n) *n = 0;
8052     if (ia) *ia = NULL;
8053     if (ja) *ja = NULL;
8054   }
8055   PetscFunctionReturn(PETSC_SUCCESS);
8056 }
8057 
8058 /*@C
8059     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8060 
8061     Collective
8062 
8063     Input Parameters:
8064 +   mat - the matrix
8065 .   ncolors - maximum color value
8066 .   n   - number of entries in colorarray
8067 -   colorarray - array indicating color for each column
8068 
8069     Output Parameter:
8070 .   iscoloring - coloring generated using colorarray information
8071 
8072     Level: developer
8073 
8074 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8075 @*/
8076 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8077 {
8078   PetscFunctionBegin;
8079   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8080   PetscValidType(mat, 1);
8081   PetscValidIntPointer(colorarray, 4);
8082   PetscValidPointer(iscoloring, 5);
8083   MatCheckPreallocated(mat, 1);
8084 
8085   if (!mat->ops->coloringpatch) {
8086     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8087   } else {
8088     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8089   }
8090   PetscFunctionReturn(PETSC_SUCCESS);
8091 }
8092 
8093 /*@
8094    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8095 
8096    Logically Collective
8097 
8098    Input Parameter:
8099 .  mat - the factored matrix to be reset
8100 
8101    Level: developer
8102 
8103    Notes:
8104    This routine should be used only with factored matrices formed by in-place
8105    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8106    format).  This option can save memory, for example, when solving nonlinear
8107    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8108    ILU(0) preconditioner.
8109 
8110    One can specify in-place ILU(0) factorization by calling
8111 .vb
8112      PCType(pc,PCILU);
8113      PCFactorSeUseInPlace(pc);
8114 .ve
8115    or by using the options -pc_type ilu -pc_factor_in_place
8116 
8117    In-place factorization ILU(0) can also be used as a local
8118    solver for the blocks within the block Jacobi or additive Schwarz
8119    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8120    for details on setting local solver options.
8121 
8122    Most users should employ the `KSP` interface for linear solvers
8123    instead of working directly with matrix algebra routines such as this.
8124    See, e.g., `KSPCreate()`.
8125 
8126 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8127 @*/
8128 PetscErrorCode MatSetUnfactored(Mat mat)
8129 {
8130   PetscFunctionBegin;
8131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8132   PetscValidType(mat, 1);
8133   MatCheckPreallocated(mat, 1);
8134   mat->factortype = MAT_FACTOR_NONE;
8135   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8136   PetscUseTypeMethod(mat, setunfactored);
8137   PetscFunctionReturn(PETSC_SUCCESS);
8138 }
8139 
8140 /*MC
8141     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8142 
8143     Synopsis:
8144     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8145 
8146     Not Collective
8147 
8148     Input Parameter:
8149 .   x - matrix
8150 
8151     Output Parameters:
8152 +   xx_v - the Fortran pointer to the array
8153 -   ierr - error code
8154 
8155     Example of Usage:
8156 .vb
8157       PetscScalar, pointer xx_v(:,:)
8158       ....
8159       call MatDenseGetArrayF90(x,xx_v,ierr)
8160       a = xx_v(3)
8161       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8162 .ve
8163 
8164     Level: advanced
8165 
8166 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8167 M*/
8168 
8169 /*MC
8170     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8171     accessed with `MatDenseGetArrayF90()`.
8172 
8173     Synopsis:
8174     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8175 
8176     Not Collective
8177 
8178     Input Parameters:
8179 +   x - matrix
8180 -   xx_v - the Fortran90 pointer to the array
8181 
8182     Output Parameter:
8183 .   ierr - error code
8184 
8185     Example of Usage:
8186 .vb
8187        PetscScalar, pointer xx_v(:,:)
8188        ....
8189        call MatDenseGetArrayF90(x,xx_v,ierr)
8190        a = xx_v(3)
8191        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8192 .ve
8193 
8194     Level: advanced
8195 
8196 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8197 M*/
8198 
8199 /*MC
8200     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8201 
8202     Synopsis:
8203     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8204 
8205     Not Collective
8206 
8207     Input Parameter:
8208 .   x - matrix
8209 
8210     Output Parameters:
8211 +   xx_v - the Fortran pointer to the array
8212 -   ierr - error code
8213 
8214     Example of Usage:
8215 .vb
8216       PetscScalar, pointer xx_v(:)
8217       ....
8218       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8219       a = xx_v(3)
8220       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8221 .ve
8222 
8223     Level: advanced
8224 
8225 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8226 M*/
8227 
8228 /*MC
8229     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8230     accessed with `MatSeqAIJGetArrayF90()`.
8231 
8232     Synopsis:
8233     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8234 
8235     Not Collective
8236 
8237     Input Parameters:
8238 +   x - matrix
8239 -   xx_v - the Fortran90 pointer to the array
8240 
8241     Output Parameter:
8242 .   ierr - error code
8243 
8244     Example of Usage:
8245 .vb
8246        PetscScalar, pointer xx_v(:)
8247        ....
8248        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8249        a = xx_v(3)
8250        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8251 .ve
8252 
8253     Level: advanced
8254 
8255 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8256 M*/
8257 
8258 /*@
8259     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8260                       as the original matrix.
8261 
8262     Collective
8263 
8264     Input Parameters:
8265 +   mat - the original matrix
8266 .   isrow - parallel `IS` containing the rows this processor should obtain
8267 .   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.
8268 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8269 
8270     Output Parameter:
8271 .   newmat - the new submatrix, of the same type as the original matrix
8272 
8273     Level: advanced
8274 
8275     Notes:
8276     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8277 
8278     Some matrix types place restrictions on the row and column indices, such
8279     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;
8280     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8281 
8282     The index sets may not have duplicate entries.
8283 
8284       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8285    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8286    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8287    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8288    you are finished using it.
8289 
8290     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8291     the input matrix.
8292 
8293     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8294 
8295    Example usage:
8296    Consider the following 8x8 matrix with 34 non-zero values, that is
8297    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8298    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8299    as follows
8300 .vb
8301             1  2  0  |  0  3  0  |  0  4
8302     Proc0   0  5  6  |  7  0  0  |  8  0
8303             9  0 10  | 11  0  0  | 12  0
8304     -------------------------------------
8305            13  0 14  | 15 16 17  |  0  0
8306     Proc1   0 18  0  | 19 20 21  |  0  0
8307             0  0  0  | 22 23  0  | 24  0
8308     -------------------------------------
8309     Proc2  25 26 27  |  0  0 28  | 29  0
8310            30  0  0  | 31 32 33  |  0 34
8311 .ve
8312 
8313     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8314 
8315 .vb
8316             2  0  |  0  3  0  |  0
8317     Proc0   5  6  |  7  0  0  |  8
8318     -------------------------------
8319     Proc1  18  0  | 19 20 21  |  0
8320     -------------------------------
8321     Proc2  26 27  |  0  0 28  | 29
8322             0  0  | 31 32 33  |  0
8323 .ve
8324 
8325 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8326 @*/
8327 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8328 {
8329   PetscMPIInt size;
8330   Mat        *local;
8331   IS          iscoltmp;
8332   PetscBool   flg;
8333 
8334   PetscFunctionBegin;
8335   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8336   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8337   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8338   PetscValidPointer(newmat, 5);
8339   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8340   PetscValidType(mat, 1);
8341   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8342   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8343 
8344   MatCheckPreallocated(mat, 1);
8345   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8346 
8347   if (!iscol || isrow == iscol) {
8348     PetscBool   stride;
8349     PetscMPIInt grabentirematrix = 0, grab;
8350     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8351     if (stride) {
8352       PetscInt first, step, n, rstart, rend;
8353       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8354       if (step == 1) {
8355         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8356         if (rstart == first) {
8357           PetscCall(ISGetLocalSize(isrow, &n));
8358           if (n == rend - rstart) grabentirematrix = 1;
8359         }
8360       }
8361     }
8362     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8363     if (grab) {
8364       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8365       if (cll == MAT_INITIAL_MATRIX) {
8366         *newmat = mat;
8367         PetscCall(PetscObjectReference((PetscObject)mat));
8368       }
8369       PetscFunctionReturn(PETSC_SUCCESS);
8370     }
8371   }
8372 
8373   if (!iscol) {
8374     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8375   } else {
8376     iscoltmp = iscol;
8377   }
8378 
8379   /* if original matrix is on just one processor then use submatrix generated */
8380   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8381     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8382     goto setproperties;
8383   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8384     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8385     *newmat = *local;
8386     PetscCall(PetscFree(local));
8387     goto setproperties;
8388   } else if (!mat->ops->createsubmatrix) {
8389     /* Create a new matrix type that implements the operation using the full matrix */
8390     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8391     switch (cll) {
8392     case MAT_INITIAL_MATRIX:
8393       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8394       break;
8395     case MAT_REUSE_MATRIX:
8396       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8397       break;
8398     default:
8399       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8400     }
8401     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8402     goto setproperties;
8403   }
8404 
8405   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8406   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8407   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8408 
8409 setproperties:
8410   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8411   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8412   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8413   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8414   PetscFunctionReturn(PETSC_SUCCESS);
8415 }
8416 
8417 /*@
8418    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8419 
8420    Not Collective
8421 
8422    Input Parameters:
8423 +  A - the matrix we wish to propagate options from
8424 -  B - the matrix we wish to propagate options to
8425 
8426    Level: beginner
8427 
8428    Note:
8429    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8430 
8431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8432 @*/
8433 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8434 {
8435   PetscFunctionBegin;
8436   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8437   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8438   B->symmetry_eternal            = A->symmetry_eternal;
8439   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8440   B->symmetric                   = A->symmetric;
8441   B->structurally_symmetric      = A->structurally_symmetric;
8442   B->spd                         = A->spd;
8443   B->hermitian                   = A->hermitian;
8444   PetscFunctionReturn(PETSC_SUCCESS);
8445 }
8446 
8447 /*@
8448    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8449    used during the assembly process to store values that belong to
8450    other processors.
8451 
8452    Not Collective
8453 
8454    Input Parameters:
8455 +  mat   - the matrix
8456 .  size  - the initial size of the stash.
8457 -  bsize - the initial size of the block-stash(if used).
8458 
8459    Options Database Keys:
8460 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8461 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8462 
8463    Level: intermediate
8464 
8465    Notes:
8466      The block-stash is used for values set with `MatSetValuesBlocked()` while
8467      the stash is used for values set with `MatSetValues()`
8468 
8469      Run with the option -info and look for output of the form
8470      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8471      to determine the appropriate value, MM, to use for size and
8472      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8473      to determine the value, BMM to use for bsize
8474 
8475 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8476 @*/
8477 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8478 {
8479   PetscFunctionBegin;
8480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8481   PetscValidType(mat, 1);
8482   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8483   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8484   PetscFunctionReturn(PETSC_SUCCESS);
8485 }
8486 
8487 /*@
8488    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8489      the matrix
8490 
8491    Neighbor-wise Collective
8492 
8493    Input Parameters:
8494 +  mat   - the matrix
8495 .  x - the vector to be multiplied by the interpolation operator
8496 -  y - the vector to be added to the result
8497 
8498    Output Parameter:
8499 .  w - the resulting vector
8500 
8501    Level: intermediate
8502 
8503    Notes:
8504     `w` may be the same vector as `y`.
8505 
8506     This allows one to use either the restriction or interpolation (its transpose)
8507     matrix to do the interpolation
8508 
8509 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8510 @*/
8511 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8512 {
8513   PetscInt M, N, Ny;
8514 
8515   PetscFunctionBegin;
8516   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8517   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8518   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8519   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8520   PetscCall(MatGetSize(A, &M, &N));
8521   PetscCall(VecGetSize(y, &Ny));
8522   if (M == Ny) {
8523     PetscCall(MatMultAdd(A, x, y, w));
8524   } else {
8525     PetscCall(MatMultTransposeAdd(A, x, y, w));
8526   }
8527   PetscFunctionReturn(PETSC_SUCCESS);
8528 }
8529 
8530 /*@
8531    MatInterpolate - y = A*x or A'*x depending on the shape of
8532      the matrix
8533 
8534    Neighbor-wise Collective
8535 
8536    Input Parameters:
8537 +  mat   - the matrix
8538 -  x - the vector to be interpolated
8539 
8540    Output Parameter:
8541 .  y - the resulting vector
8542 
8543    Level: intermediate
8544 
8545    Note:
8546     This allows one to use either the restriction or interpolation (its transpose)
8547     matrix to do the interpolation
8548 
8549 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8550 @*/
8551 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8552 {
8553   PetscInt M, N, Ny;
8554 
8555   PetscFunctionBegin;
8556   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8557   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8558   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8559   PetscCall(MatGetSize(A, &M, &N));
8560   PetscCall(VecGetSize(y, &Ny));
8561   if (M == Ny) {
8562     PetscCall(MatMult(A, x, y));
8563   } else {
8564     PetscCall(MatMultTranspose(A, x, y));
8565   }
8566   PetscFunctionReturn(PETSC_SUCCESS);
8567 }
8568 
8569 /*@
8570    MatRestrict - y = A*x or A'*x
8571 
8572    Neighbor-wise Collective
8573 
8574    Input Parameters:
8575 +  mat   - the matrix
8576 -  x - the vector to be restricted
8577 
8578    Output Parameter:
8579 .  y - the resulting vector
8580 
8581    Level: intermediate
8582 
8583    Note:
8584     This allows one to use either the restriction or interpolation (its transpose)
8585     matrix to do the restriction
8586 
8587 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8588 @*/
8589 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8590 {
8591   PetscInt M, N, Ny;
8592 
8593   PetscFunctionBegin;
8594   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8595   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8596   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8597   PetscCall(MatGetSize(A, &M, &N));
8598   PetscCall(VecGetSize(y, &Ny));
8599   if (M == Ny) {
8600     PetscCall(MatMult(A, x, y));
8601   } else {
8602     PetscCall(MatMultTranspose(A, x, y));
8603   }
8604   PetscFunctionReturn(PETSC_SUCCESS);
8605 }
8606 
8607 /*@
8608    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8609 
8610    Neighbor-wise Collective
8611 
8612    Input Parameters:
8613 +  mat   - the matrix
8614 .  x - the input dense matrix to be multiplied
8615 -  w - the input dense matrix to be added to the result
8616 
8617    Output Parameter:
8618 .  y - the output dense matrix
8619 
8620    Level: intermediate
8621 
8622    Note:
8623     This allows one to use either the restriction or interpolation (its transpose)
8624     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8625     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8626 
8627 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8628 @*/
8629 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8630 {
8631   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8632   PetscBool trans = PETSC_TRUE;
8633   MatReuse  reuse = MAT_INITIAL_MATRIX;
8634 
8635   PetscFunctionBegin;
8636   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8637   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8638   PetscValidType(x, 2);
8639   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8640   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8641   PetscCall(MatGetSize(A, &M, &N));
8642   PetscCall(MatGetSize(x, &Mx, &Nx));
8643   if (N == Mx) trans = PETSC_FALSE;
8644   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);
8645   Mo = trans ? N : M;
8646   if (*y) {
8647     PetscCall(MatGetSize(*y, &My, &Ny));
8648     if (Mo == My && Nx == Ny) {
8649       reuse = MAT_REUSE_MATRIX;
8650     } else {
8651       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);
8652       PetscCall(MatDestroy(y));
8653     }
8654   }
8655 
8656   if (w && *y == w) { /* this is to minimize changes in PCMG */
8657     PetscBool flg;
8658 
8659     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8660     if (w) {
8661       PetscInt My, Ny, Mw, Nw;
8662 
8663       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8664       PetscCall(MatGetSize(*y, &My, &Ny));
8665       PetscCall(MatGetSize(w, &Mw, &Nw));
8666       if (!flg || My != Mw || Ny != Nw) w = NULL;
8667     }
8668     if (!w) {
8669       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8670       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8671       PetscCall(PetscObjectDereference((PetscObject)w));
8672     } else {
8673       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8674     }
8675   }
8676   if (!trans) {
8677     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8678   } else {
8679     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8680   }
8681   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8682   PetscFunctionReturn(PETSC_SUCCESS);
8683 }
8684 
8685 /*@
8686    MatMatInterpolate - Y = A*X or A'*X
8687 
8688    Neighbor-wise Collective
8689 
8690    Input Parameters:
8691 +  mat   - the matrix
8692 -  x - the input dense matrix
8693 
8694    Output Parameter:
8695 .  y - the output dense matrix
8696 
8697    Level: intermediate
8698 
8699    Note:
8700     This allows one to use either the restriction or interpolation (its transpose)
8701     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8702     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8703 
8704 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8705 @*/
8706 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8707 {
8708   PetscFunctionBegin;
8709   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8710   PetscFunctionReturn(PETSC_SUCCESS);
8711 }
8712 
8713 /*@
8714    MatMatRestrict - Y = A*X or A'*X
8715 
8716    Neighbor-wise Collective
8717 
8718    Input Parameters:
8719 +  mat   - the matrix
8720 -  x - the input dense matrix
8721 
8722    Output Parameter:
8723 .  y - the output dense matrix
8724 
8725    Level: intermediate
8726 
8727    Note:
8728     This allows one to use either the restriction or interpolation (its transpose)
8729     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8730     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8731 
8732 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8733 @*/
8734 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8735 {
8736   PetscFunctionBegin;
8737   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8738   PetscFunctionReturn(PETSC_SUCCESS);
8739 }
8740 
8741 /*@
8742    MatGetNullSpace - retrieves the null space of a matrix.
8743 
8744    Logically Collective
8745 
8746    Input Parameters:
8747 +  mat - the matrix
8748 -  nullsp - the null space object
8749 
8750    Level: developer
8751 
8752 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8753 @*/
8754 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8755 {
8756   PetscFunctionBegin;
8757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8758   PetscValidPointer(nullsp, 2);
8759   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8760   PetscFunctionReturn(PETSC_SUCCESS);
8761 }
8762 
8763 /*@
8764    MatSetNullSpace - attaches a null space to a matrix.
8765 
8766    Logically Collective
8767 
8768    Input Parameters:
8769 +  mat - the matrix
8770 -  nullsp - the null space object
8771 
8772    Level: advanced
8773 
8774    Notes:
8775       This null space is used by the `KSP` linear solvers to solve singular systems.
8776 
8777       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`
8778 
8779       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
8780       to zero but the linear system will still be solved in a least squares sense.
8781 
8782       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8783    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).
8784    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
8785    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
8786    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).
8787    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8788 
8789     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8790     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8791     routine also automatically calls `MatSetTransposeNullSpace()`.
8792 
8793     The user should call `MatNullSpaceDestroy()`.
8794 
8795 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8796           `KSPSetPCSide()`
8797 @*/
8798 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8799 {
8800   PetscFunctionBegin;
8801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8802   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8803   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8804   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8805   mat->nullsp = nullsp;
8806   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8807   PetscFunctionReturn(PETSC_SUCCESS);
8808 }
8809 
8810 /*@
8811    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8812 
8813    Logically Collective
8814 
8815    Input Parameters:
8816 +  mat - the matrix
8817 -  nullsp - the null space object
8818 
8819    Level: developer
8820 
8821 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8822 @*/
8823 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8824 {
8825   PetscFunctionBegin;
8826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8827   PetscValidType(mat, 1);
8828   PetscValidPointer(nullsp, 2);
8829   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8830   PetscFunctionReturn(PETSC_SUCCESS);
8831 }
8832 
8833 /*@
8834    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8835 
8836    Logically Collective
8837 
8838    Input Parameters:
8839 +  mat - the matrix
8840 -  nullsp - the null space object
8841 
8842    Level: advanced
8843 
8844    Notes:
8845    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8846 
8847    See `MatSetNullSpace()`
8848 
8849 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8850 @*/
8851 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8852 {
8853   PetscFunctionBegin;
8854   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8855   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8856   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8857   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8858   mat->transnullsp = nullsp;
8859   PetscFunctionReturn(PETSC_SUCCESS);
8860 }
8861 
8862 /*@
8863    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8864         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8865 
8866    Logically Collective
8867 
8868    Input Parameters:
8869 +  mat - the matrix
8870 -  nullsp - the null space object
8871 
8872    Level: advanced
8873 
8874    Notes:
8875    Overwrites any previous near null space that may have been attached
8876 
8877    You can remove the null space by calling this routine with an nullsp of `NULL`
8878 
8879 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8880 @*/
8881 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8882 {
8883   PetscFunctionBegin;
8884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8885   PetscValidType(mat, 1);
8886   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8887   MatCheckPreallocated(mat, 1);
8888   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8889   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8890   mat->nearnullsp = nullsp;
8891   PetscFunctionReturn(PETSC_SUCCESS);
8892 }
8893 
8894 /*@
8895    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8896 
8897    Not Collective
8898 
8899    Input Parameter:
8900 .  mat - the matrix
8901 
8902    Output Parameter:
8903 .  nullsp - the null space object, `NULL` if not set
8904 
8905    Level: advanced
8906 
8907 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8908 @*/
8909 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8910 {
8911   PetscFunctionBegin;
8912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8913   PetscValidType(mat, 1);
8914   PetscValidPointer(nullsp, 2);
8915   MatCheckPreallocated(mat, 1);
8916   *nullsp = mat->nearnullsp;
8917   PetscFunctionReturn(PETSC_SUCCESS);
8918 }
8919 
8920 /*@C
8921    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8922 
8923    Collective
8924 
8925    Input Parameters:
8926 +  mat - the matrix
8927 .  row - row/column permutation
8928 -  info - information on desired factorization process
8929 
8930    Level: developer
8931 
8932    Notes:
8933    Probably really in-place only when level of fill is zero, otherwise allocates
8934    new space to store factored matrix and deletes previous memory.
8935 
8936    Most users should employ the `KSP` interface for linear solvers
8937    instead of working directly with matrix algebra routines such as this.
8938    See, e.g., `KSPCreate()`.
8939 
8940    Developer Note:
8941    The Fortran interface is not autogenerated as the
8942    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8943 
8944 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8945 @*/
8946 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8947 {
8948   PetscFunctionBegin;
8949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8950   PetscValidType(mat, 1);
8951   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8952   PetscValidPointer(info, 3);
8953   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8954   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8955   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8956   MatCheckPreallocated(mat, 1);
8957   PetscUseTypeMethod(mat, iccfactor, row, info);
8958   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8959   PetscFunctionReturn(PETSC_SUCCESS);
8960 }
8961 
8962 /*@
8963    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8964          ghosted ones.
8965 
8966    Not Collective
8967 
8968    Input Parameters:
8969 +  mat - the matrix
8970 -  diag - the diagonal values, including ghost ones
8971 
8972    Level: developer
8973 
8974    Notes:
8975     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8976 
8977     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8978 
8979 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8980 @*/
8981 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8982 {
8983   PetscMPIInt size;
8984 
8985   PetscFunctionBegin;
8986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8987   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8988   PetscValidType(mat, 1);
8989 
8990   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8991   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8992   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8993   if (size == 1) {
8994     PetscInt n, m;
8995     PetscCall(VecGetSize(diag, &n));
8996     PetscCall(MatGetSize(mat, NULL, &m));
8997     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8998     PetscCall(MatDiagonalScale(mat, NULL, diag));
8999   } else {
9000     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9001   }
9002   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9003   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9004   PetscFunctionReturn(PETSC_SUCCESS);
9005 }
9006 
9007 /*@
9008    MatGetInertia - Gets the inertia from a factored matrix
9009 
9010    Collective
9011 
9012    Input Parameter:
9013 .  mat - the matrix
9014 
9015    Output Parameters:
9016 +   nneg - number of negative eigenvalues
9017 .   nzero - number of zero eigenvalues
9018 -   npos - number of positive eigenvalues
9019 
9020    Level: advanced
9021 
9022    Note:
9023     Matrix must have been factored by `MatCholeskyFactor()`
9024 
9025 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9026 @*/
9027 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9028 {
9029   PetscFunctionBegin;
9030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9031   PetscValidType(mat, 1);
9032   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9033   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9034   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9035   PetscFunctionReturn(PETSC_SUCCESS);
9036 }
9037 
9038 /*@C
9039    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9040 
9041    Neighbor-wise Collective
9042 
9043    Input Parameters:
9044 +  mat - the factored matrix obtained with `MatGetFactor()`
9045 -  b - the right-hand-side vectors
9046 
9047    Output Parameter:
9048 .  x - the result vectors
9049 
9050    Level: developer
9051 
9052    Note:
9053    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9054    call `MatSolves`(A,x,x).
9055 
9056 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9057 @*/
9058 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9059 {
9060   PetscFunctionBegin;
9061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9062   PetscValidType(mat, 1);
9063   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9064   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9065   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9066 
9067   MatCheckPreallocated(mat, 1);
9068   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9069   PetscUseTypeMethod(mat, solves, b, x);
9070   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9071   PetscFunctionReturn(PETSC_SUCCESS);
9072 }
9073 
9074 /*@
9075    MatIsSymmetric - Test whether a matrix is symmetric
9076 
9077    Collective
9078 
9079    Input Parameters:
9080 +  A - the matrix to test
9081 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9082 
9083    Output Parameter:
9084 .  flg - the result
9085 
9086    Level: intermediate
9087 
9088    Notes:
9089     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9090 
9091     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9092 
9093     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9094     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9095 
9096 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9097           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9098 @*/
9099 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9100 {
9101   PetscFunctionBegin;
9102   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9103   PetscValidBoolPointer(flg, 3);
9104 
9105   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9106   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9107   else {
9108     PetscUseTypeMethod(A, issymmetric, tol, flg);
9109     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9110   }
9111   PetscFunctionReturn(PETSC_SUCCESS);
9112 }
9113 
9114 /*@
9115    MatIsHermitian - Test whether a matrix is Hermitian
9116 
9117    Collective
9118 
9119    Input Parameters:
9120 +  A - the matrix to test
9121 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9122 
9123    Output Parameter:
9124 .  flg - the result
9125 
9126    Level: intermediate
9127 
9128    Notes:
9129     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9130 
9131     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9132 
9133     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9134     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9135 
9136 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9137           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9138 @*/
9139 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9140 {
9141   PetscFunctionBegin;
9142   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9143   PetscValidBoolPointer(flg, 3);
9144 
9145   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9146   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9147   else {
9148     PetscUseTypeMethod(A, ishermitian, tol, flg);
9149     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9150   }
9151   PetscFunctionReturn(PETSC_SUCCESS);
9152 }
9153 
9154 /*@
9155    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9156 
9157    Not Collective
9158 
9159    Input Parameter:
9160 .  A - the matrix to check
9161 
9162    Output Parameters:
9163 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9164 -  flg - the result (only valid if set is `PETSC_TRUE`)
9165 
9166    Level: advanced
9167 
9168    Notes:
9169    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9170    if you want it explicitly checked
9171 
9172     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9173     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9174 
9175 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9176 @*/
9177 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9178 {
9179   PetscFunctionBegin;
9180   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9181   PetscValidBoolPointer(set, 2);
9182   PetscValidBoolPointer(flg, 3);
9183   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9184     *set = PETSC_TRUE;
9185     *flg = PetscBool3ToBool(A->symmetric);
9186   } else {
9187     *set = PETSC_FALSE;
9188   }
9189   PetscFunctionReturn(PETSC_SUCCESS);
9190 }
9191 
9192 /*@
9193    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9194 
9195    Not Collective
9196 
9197    Input Parameter:
9198 .  A - the matrix to check
9199 
9200    Output Parameters:
9201 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9202 -  flg - the result (only valid if set is `PETSC_TRUE`)
9203 
9204    Level: advanced
9205 
9206    Notes:
9207    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9208 
9209    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9210    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9211 
9212 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9213 @*/
9214 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9215 {
9216   PetscFunctionBegin;
9217   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9218   PetscValidBoolPointer(set, 2);
9219   PetscValidBoolPointer(flg, 3);
9220   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9221     *set = PETSC_TRUE;
9222     *flg = PetscBool3ToBool(A->spd);
9223   } else {
9224     *set = PETSC_FALSE;
9225   }
9226   PetscFunctionReturn(PETSC_SUCCESS);
9227 }
9228 
9229 /*@
9230    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9231 
9232    Not Collective
9233 
9234    Input Parameter:
9235 .  A - the matrix to check
9236 
9237    Output Parameters:
9238 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9239 -  flg - the result (only valid if set is `PETSC_TRUE`)
9240 
9241    Level: advanced
9242 
9243    Notes:
9244    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9245    if you want it explicitly checked
9246 
9247    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9248    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9249 
9250 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9251 @*/
9252 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9253 {
9254   PetscFunctionBegin;
9255   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9256   PetscValidBoolPointer(set, 2);
9257   PetscValidBoolPointer(flg, 3);
9258   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9259     *set = PETSC_TRUE;
9260     *flg = PetscBool3ToBool(A->hermitian);
9261   } else {
9262     *set = PETSC_FALSE;
9263   }
9264   PetscFunctionReturn(PETSC_SUCCESS);
9265 }
9266 
9267 /*@
9268    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9269 
9270    Collective
9271 
9272    Input Parameter:
9273 .  A - the matrix to test
9274 
9275    Output Parameter:
9276 .  flg - the result
9277 
9278    Level: intermediate
9279 
9280    Notes:
9281    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9282 
9283    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
9284    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9285 
9286 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9287 @*/
9288 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9289 {
9290   PetscFunctionBegin;
9291   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9292   PetscValidBoolPointer(flg, 2);
9293   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9294     *flg = PetscBool3ToBool(A->structurally_symmetric);
9295   } else {
9296     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9297     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9298   }
9299   PetscFunctionReturn(PETSC_SUCCESS);
9300 }
9301 
9302 /*@
9303    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9304 
9305    Not Collective
9306 
9307    Input Parameter:
9308 .  A - the matrix to check
9309 
9310    Output Parameters:
9311 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9312 -  flg - the result (only valid if set is PETSC_TRUE)
9313 
9314    Level: advanced
9315 
9316    Notes:
9317    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
9318    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9319 
9320    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9321 
9322 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9323 @*/
9324 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9325 {
9326   PetscFunctionBegin;
9327   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9328   PetscValidBoolPointer(set, 2);
9329   PetscValidBoolPointer(flg, 3);
9330   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9331     *set = PETSC_TRUE;
9332     *flg = PetscBool3ToBool(A->structurally_symmetric);
9333   } else {
9334     *set = PETSC_FALSE;
9335   }
9336   PetscFunctionReturn(PETSC_SUCCESS);
9337 }
9338 
9339 /*@
9340    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9341        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9342 
9343     Not Collective
9344 
9345    Input Parameter:
9346 .   mat - the matrix
9347 
9348    Output Parameters:
9349 +   nstash   - the size of the stash
9350 .   reallocs - the number of additional mallocs incurred.
9351 .   bnstash   - the size of the block stash
9352 -   breallocs - the number of additional mallocs incurred.in the block stash
9353 
9354    Level: advanced
9355 
9356 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9357 @*/
9358 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9359 {
9360   PetscFunctionBegin;
9361   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9362   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9363   PetscFunctionReturn(PETSC_SUCCESS);
9364 }
9365 
9366 /*@C
9367    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9368    parallel layout, `PetscLayout` for rows and columns
9369 
9370    Collective
9371 
9372    Input Parameter:
9373 .  mat - the matrix
9374 
9375    Output Parameters:
9376 +   right - (optional) vector that the matrix can be multiplied against
9377 -   left - (optional) vector that the matrix vector product can be stored in
9378 
9379   Level: advanced
9380 
9381    Notes:
9382     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()`.
9383 
9384     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9385 
9386 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9387 @*/
9388 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9389 {
9390   PetscFunctionBegin;
9391   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9392   PetscValidType(mat, 1);
9393   if (mat->ops->getvecs) {
9394     PetscUseTypeMethod(mat, getvecs, right, left);
9395   } else {
9396     PetscInt rbs, cbs;
9397     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9398     if (right) {
9399       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9400       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9401       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9402       PetscCall(VecSetBlockSize(*right, cbs));
9403       PetscCall(VecSetType(*right, mat->defaultvectype));
9404 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9405       if (mat->boundtocpu && mat->bindingpropagates) {
9406         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9407         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9408       }
9409 #endif
9410       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9411     }
9412     if (left) {
9413       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9414       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9415       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9416       PetscCall(VecSetBlockSize(*left, rbs));
9417       PetscCall(VecSetType(*left, mat->defaultvectype));
9418 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9419       if (mat->boundtocpu && mat->bindingpropagates) {
9420         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9421         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9422       }
9423 #endif
9424       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9425     }
9426   }
9427   PetscFunctionReturn(PETSC_SUCCESS);
9428 }
9429 
9430 /*@C
9431    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9432      with default values.
9433 
9434    Not Collective
9435 
9436    Input Parameter:
9437 .    info - the `MatFactorInfo` data structure
9438 
9439    Level: developer
9440 
9441    Notes:
9442     The solvers are generally used through the `KSP` and `PC` objects, for example
9443           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9444 
9445     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9446 
9447    Developer Note:
9448    The Fortran interface is not autogenerated as the
9449    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9450 
9451 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9452 @*/
9453 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9454 {
9455   PetscFunctionBegin;
9456   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9457   PetscFunctionReturn(PETSC_SUCCESS);
9458 }
9459 
9460 /*@
9461    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9462 
9463    Collective
9464 
9465    Input Parameters:
9466 +  mat - the factored matrix
9467 -  is - the index set defining the Schur indices (0-based)
9468 
9469    Level: advanced
9470 
9471    Notes:
9472     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9473 
9474    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9475 
9476    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9477 
9478 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9479           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9480 @*/
9481 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9482 {
9483   PetscErrorCode (*f)(Mat, IS);
9484 
9485   PetscFunctionBegin;
9486   PetscValidType(mat, 1);
9487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9488   PetscValidType(is, 2);
9489   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9490   PetscCheckSameComm(mat, 1, is, 2);
9491   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9492   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9493   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9494   PetscCall(MatDestroy(&mat->schur));
9495   PetscCall((*f)(mat, is));
9496   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9497   PetscFunctionReturn(PETSC_SUCCESS);
9498 }
9499 
9500 /*@
9501   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9502 
9503    Logically Collective
9504 
9505    Input Parameters:
9506 +  F - the factored matrix obtained by calling `MatGetFactor()`
9507 .  S - location where to return the Schur complement, can be `NULL`
9508 -  status - the status of the Schur complement matrix, can be `NULL`
9509 
9510    Level: advanced
9511 
9512    Notes:
9513    You must call `MatFactorSetSchurIS()` before calling this routine.
9514 
9515    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9516 
9517    The routine provides a copy of the Schur matrix stored within the solver data structures.
9518    The caller must destroy the object when it is no longer needed.
9519    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9520 
9521    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)
9522 
9523    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9524 
9525    Developer Note:
9526     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9527    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9528 
9529 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9530 @*/
9531 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9532 {
9533   PetscFunctionBegin;
9534   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9535   if (S) PetscValidPointer(S, 2);
9536   if (status) PetscValidPointer(status, 3);
9537   if (S) {
9538     PetscErrorCode (*f)(Mat, Mat *);
9539 
9540     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9541     if (f) {
9542       PetscCall((*f)(F, S));
9543     } else {
9544       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9545     }
9546   }
9547   if (status) *status = F->schur_status;
9548   PetscFunctionReturn(PETSC_SUCCESS);
9549 }
9550 
9551 /*@
9552   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9553 
9554    Logically Collective
9555 
9556    Input Parameters:
9557 +  F - the factored matrix obtained by calling `MatGetFactor()`
9558 .  *S - location where to return the Schur complement, can be `NULL`
9559 -  status - the status of the Schur complement matrix, can be `NULL`
9560 
9561    Level: advanced
9562 
9563    Notes:
9564    You must call `MatFactorSetSchurIS()` before calling this routine.
9565 
9566    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9567 
9568    The routine returns a the Schur Complement stored within the data structures of the solver.
9569 
9570    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9571 
9572    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9573 
9574    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9575 
9576    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9577 
9578 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9579 @*/
9580 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9581 {
9582   PetscFunctionBegin;
9583   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9584   if (S) PetscValidPointer(S, 2);
9585   if (status) PetscValidPointer(status, 3);
9586   if (S) *S = F->schur;
9587   if (status) *status = F->schur_status;
9588   PetscFunctionReturn(PETSC_SUCCESS);
9589 }
9590 
9591 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9592 {
9593   Mat S = F->schur;
9594 
9595   PetscFunctionBegin;
9596   switch (F->schur_status) {
9597   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9598   case MAT_FACTOR_SCHUR_INVERTED:
9599     if (S) {
9600       S->ops->solve             = NULL;
9601       S->ops->matsolve          = NULL;
9602       S->ops->solvetranspose    = NULL;
9603       S->ops->matsolvetranspose = NULL;
9604       S->ops->solveadd          = NULL;
9605       S->ops->solvetransposeadd = NULL;
9606       S->factortype             = MAT_FACTOR_NONE;
9607       PetscCall(PetscFree(S->solvertype));
9608     }
9609   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9610     break;
9611   default:
9612     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9613   }
9614   PetscFunctionReturn(PETSC_SUCCESS);
9615 }
9616 
9617 /*@
9618   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9619 
9620    Logically Collective
9621 
9622    Input Parameters:
9623 +  F - the factored matrix obtained by calling `MatGetFactor()`
9624 .  *S - location where the Schur complement is stored
9625 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9626 
9627    Level: advanced
9628 
9629 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9630 @*/
9631 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9632 {
9633   PetscFunctionBegin;
9634   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9635   if (S) {
9636     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9637     *S = NULL;
9638   }
9639   F->schur_status = status;
9640   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9641   PetscFunctionReturn(PETSC_SUCCESS);
9642 }
9643 
9644 /*@
9645   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9646 
9647    Logically Collective
9648 
9649    Input Parameters:
9650 +  F - the factored matrix obtained by calling `MatGetFactor()`
9651 .  rhs - location where the right hand side of the Schur complement system is stored
9652 -  sol - location where the solution of the Schur complement system has to be returned
9653 
9654    Level: advanced
9655 
9656    Notes:
9657    The sizes of the vectors should match the size of the Schur complement
9658 
9659    Must be called after `MatFactorSetSchurIS()`
9660 
9661 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9662 @*/
9663 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9664 {
9665   PetscFunctionBegin;
9666   PetscValidType(F, 1);
9667   PetscValidType(rhs, 2);
9668   PetscValidType(sol, 3);
9669   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9670   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9671   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9672   PetscCheckSameComm(F, 1, rhs, 2);
9673   PetscCheckSameComm(F, 1, sol, 3);
9674   PetscCall(MatFactorFactorizeSchurComplement(F));
9675   switch (F->schur_status) {
9676   case MAT_FACTOR_SCHUR_FACTORED:
9677     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9678     break;
9679   case MAT_FACTOR_SCHUR_INVERTED:
9680     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9681     break;
9682   default:
9683     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9684   }
9685   PetscFunctionReturn(PETSC_SUCCESS);
9686 }
9687 
9688 /*@
9689   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9690 
9691    Logically Collective
9692 
9693    Input Parameters:
9694 +  F - the factored matrix obtained by calling `MatGetFactor()`
9695 .  rhs - location where the right hand side of the Schur complement system is stored
9696 -  sol - location where the solution of the Schur complement system has to be returned
9697 
9698    Level: advanced
9699 
9700    Notes:
9701    The sizes of the vectors should match the size of the Schur complement
9702 
9703    Must be called after `MatFactorSetSchurIS()`
9704 
9705 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9706 @*/
9707 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9708 {
9709   PetscFunctionBegin;
9710   PetscValidType(F, 1);
9711   PetscValidType(rhs, 2);
9712   PetscValidType(sol, 3);
9713   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9714   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9715   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9716   PetscCheckSameComm(F, 1, rhs, 2);
9717   PetscCheckSameComm(F, 1, sol, 3);
9718   PetscCall(MatFactorFactorizeSchurComplement(F));
9719   switch (F->schur_status) {
9720   case MAT_FACTOR_SCHUR_FACTORED:
9721     PetscCall(MatSolve(F->schur, rhs, sol));
9722     break;
9723   case MAT_FACTOR_SCHUR_INVERTED:
9724     PetscCall(MatMult(F->schur, rhs, sol));
9725     break;
9726   default:
9727     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9728   }
9729   PetscFunctionReturn(PETSC_SUCCESS);
9730 }
9731 
9732 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9733 #if PetscDefined(HAVE_CUDA)
9734 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9735 #endif
9736 
9737 /* Schur status updated in the interface */
9738 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9739 {
9740   Mat S = F->schur;
9741 
9742   PetscFunctionBegin;
9743   if (S) {
9744     PetscMPIInt size;
9745     PetscBool   isdense, isdensecuda;
9746 
9747     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9748     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9749     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9750     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9751     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9752     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9753     if (isdense) {
9754       PetscCall(MatSeqDenseInvertFactors_Private(S));
9755     } else if (isdensecuda) {
9756 #if defined(PETSC_HAVE_CUDA)
9757       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9758 #endif
9759     }
9760     // HIP??????????????
9761     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9762   }
9763   PetscFunctionReturn(PETSC_SUCCESS);
9764 }
9765 
9766 /*@
9767   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9768 
9769    Logically Collective
9770 
9771    Input Parameter:
9772 .  F - the factored matrix obtained by calling `MatGetFactor()`
9773 
9774    Level: advanced
9775 
9776    Notes:
9777     Must be called after `MatFactorSetSchurIS()`.
9778 
9779    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9780 
9781 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9782 @*/
9783 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9784 {
9785   PetscFunctionBegin;
9786   PetscValidType(F, 1);
9787   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9788   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9789   PetscCall(MatFactorFactorizeSchurComplement(F));
9790   PetscCall(MatFactorInvertSchurComplement_Private(F));
9791   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9792   PetscFunctionReturn(PETSC_SUCCESS);
9793 }
9794 
9795 /*@
9796   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9797 
9798    Logically Collective
9799 
9800    Input Parameter:
9801 .  F - the factored matrix obtained by calling `MatGetFactor()`
9802 
9803    Level: advanced
9804 
9805    Note:
9806     Must be called after `MatFactorSetSchurIS()`
9807 
9808 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9809 @*/
9810 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9811 {
9812   MatFactorInfo info;
9813 
9814   PetscFunctionBegin;
9815   PetscValidType(F, 1);
9816   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9817   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9818   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9819   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9820   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9821     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9822   } else {
9823     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9824   }
9825   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9826   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9827   PetscFunctionReturn(PETSC_SUCCESS);
9828 }
9829 
9830 /*@
9831    MatPtAP - Creates the matrix product C = P^T * A * P
9832 
9833    Neighbor-wise Collective
9834 
9835    Input Parameters:
9836 +  A - the matrix
9837 .  P - the projection matrix
9838 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9839 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9840           if the result is a dense matrix this is irrelevant
9841 
9842    Output Parameter:
9843 .  C - the product matrix
9844 
9845    Level: intermediate
9846 
9847    Notes:
9848    C will be created and must be destroyed by the user with `MatDestroy()`.
9849 
9850    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9851 
9852    Developer Note:
9853    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9854 
9855 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9856 @*/
9857 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9858 {
9859   PetscFunctionBegin;
9860   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9861   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9862 
9863   if (scall == MAT_INITIAL_MATRIX) {
9864     PetscCall(MatProductCreate(A, P, NULL, C));
9865     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9866     PetscCall(MatProductSetAlgorithm(*C, "default"));
9867     PetscCall(MatProductSetFill(*C, fill));
9868 
9869     (*C)->product->api_user = PETSC_TRUE;
9870     PetscCall(MatProductSetFromOptions(*C));
9871     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);
9872     PetscCall(MatProductSymbolic(*C));
9873   } else { /* scall == MAT_REUSE_MATRIX */
9874     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9875   }
9876 
9877   PetscCall(MatProductNumeric(*C));
9878   (*C)->symmetric = A->symmetric;
9879   (*C)->spd       = A->spd;
9880   PetscFunctionReturn(PETSC_SUCCESS);
9881 }
9882 
9883 /*@
9884    MatRARt - Creates the matrix product C = R * A * R^T
9885 
9886    Neighbor-wise Collective
9887 
9888    Input Parameters:
9889 +  A - the matrix
9890 .  R - the projection matrix
9891 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9892 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9893           if the result is a dense matrix this is irrelevant
9894 
9895    Output Parameter:
9896 .  C - the product matrix
9897 
9898    Level: intermediate
9899 
9900    Notes:
9901    C will be created and must be destroyed by the user with `MatDestroy()`.
9902 
9903    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9904 
9905    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9906    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9907    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9908    We recommend using MatPtAP().
9909 
9910 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9911 @*/
9912 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9913 {
9914   PetscFunctionBegin;
9915   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9916   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9917 
9918   if (scall == MAT_INITIAL_MATRIX) {
9919     PetscCall(MatProductCreate(A, R, NULL, C));
9920     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9921     PetscCall(MatProductSetAlgorithm(*C, "default"));
9922     PetscCall(MatProductSetFill(*C, fill));
9923 
9924     (*C)->product->api_user = PETSC_TRUE;
9925     PetscCall(MatProductSetFromOptions(*C));
9926     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);
9927     PetscCall(MatProductSymbolic(*C));
9928   } else { /* scall == MAT_REUSE_MATRIX */
9929     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9930   }
9931 
9932   PetscCall(MatProductNumeric(*C));
9933   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9934   PetscFunctionReturn(PETSC_SUCCESS);
9935 }
9936 
9937 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9938 {
9939   PetscFunctionBegin;
9940   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9941 
9942   if (scall == MAT_INITIAL_MATRIX) {
9943     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9944     PetscCall(MatProductCreate(A, B, NULL, C));
9945     PetscCall(MatProductSetType(*C, ptype));
9946     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9947     PetscCall(MatProductSetFill(*C, fill));
9948 
9949     (*C)->product->api_user = PETSC_TRUE;
9950     PetscCall(MatProductSetFromOptions(*C));
9951     PetscCall(MatProductSymbolic(*C));
9952   } else { /* scall == MAT_REUSE_MATRIX */
9953     Mat_Product *product = (*C)->product;
9954     PetscBool    isdense;
9955 
9956     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9957     if (isdense && product && product->type != ptype) {
9958       PetscCall(MatProductClear(*C));
9959       product = NULL;
9960     }
9961     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9962     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9963       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9964       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9965       product           = (*C)->product;
9966       product->fill     = fill;
9967       product->api_user = PETSC_TRUE;
9968       product->clear    = PETSC_TRUE;
9969 
9970       PetscCall(MatProductSetType(*C, ptype));
9971       PetscCall(MatProductSetFromOptions(*C));
9972       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);
9973       PetscCall(MatProductSymbolic(*C));
9974     } else { /* user may change input matrices A or B when REUSE */
9975       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9976     }
9977   }
9978   PetscCall(MatProductNumeric(*C));
9979   PetscFunctionReturn(PETSC_SUCCESS);
9980 }
9981 
9982 /*@
9983    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9984 
9985    Neighbor-wise Collective
9986 
9987    Input Parameters:
9988 +  A - the left matrix
9989 .  B - the right matrix
9990 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9991 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9992           if the result is a dense matrix this is irrelevant
9993 
9994    Output Parameter:
9995 .  C - the product matrix
9996 
9997    Notes:
9998    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9999 
10000    `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
10001    call to this function with `MAT_INITIAL_MATRIX`.
10002 
10003    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10004 
10005    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`,
10006    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10007 
10008    Example of Usage:
10009 .vb
10010      MatProductCreate(A,B,NULL,&C);
10011      MatProductSetType(C,MATPRODUCT_AB);
10012      MatProductSymbolic(C);
10013      MatProductNumeric(C); // compute C=A * B
10014      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10015      MatProductNumeric(C);
10016      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10017      MatProductNumeric(C);
10018 .ve
10019 
10020    Level: intermediate
10021 
10022 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10023 @*/
10024 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10025 {
10026   PetscFunctionBegin;
10027   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10028   PetscFunctionReturn(PETSC_SUCCESS);
10029 }
10030 
10031 /*@
10032    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10033 
10034    Neighbor-wise Collective
10035 
10036    Input Parameters:
10037 +  A - the left matrix
10038 .  B - the right matrix
10039 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10040 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10041 
10042    Output Parameter:
10043 .  C - the product matrix
10044 
10045    Level: intermediate
10046 
10047    Notes:
10048    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10049 
10050    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10051 
10052    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10053    actually needed.
10054 
10055    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10056    and for pairs of `MATMPIDENSE` matrices.
10057 
10058    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10059 
10060    Options Database Keys:
10061 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10062               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10063               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10064 
10065 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10066 @*/
10067 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10068 {
10069   PetscFunctionBegin;
10070   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10071   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10072   PetscFunctionReturn(PETSC_SUCCESS);
10073 }
10074 
10075 /*@
10076    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10077 
10078    Neighbor-wise Collective
10079 
10080    Input Parameters:
10081 +  A - the left matrix
10082 .  B - the right matrix
10083 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10084 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10085 
10086    Output Parameter:
10087 .  C - the product matrix
10088 
10089    Level: intermediate
10090 
10091    Notes:
10092    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10093 
10094    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10095 
10096    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10097 
10098    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10099    actually needed.
10100 
10101    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10102    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10103 
10104 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10105 @*/
10106 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10107 {
10108   PetscFunctionBegin;
10109   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10110   PetscFunctionReturn(PETSC_SUCCESS);
10111 }
10112 
10113 /*@
10114    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10115 
10116    Neighbor-wise Collective
10117 
10118    Input Parameters:
10119 +  A - the left matrix
10120 .  B - the middle matrix
10121 .  C - the right matrix
10122 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10123 -  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
10124           if the result is a dense matrix this is irrelevant
10125 
10126    Output Parameter:
10127 .  D - the product matrix
10128 
10129    Level: intermediate
10130 
10131    Notes:
10132    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10133 
10134    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10135 
10136    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10137 
10138    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10139    actually needed.
10140 
10141    If you have many matrices with the same non-zero structure to multiply, you
10142    should use `MAT_REUSE_MATRIX` in all calls but the first
10143 
10144 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10145 @*/
10146 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10147 {
10148   PetscFunctionBegin;
10149   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10150   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10151 
10152   if (scall == MAT_INITIAL_MATRIX) {
10153     PetscCall(MatProductCreate(A, B, C, D));
10154     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10155     PetscCall(MatProductSetAlgorithm(*D, "default"));
10156     PetscCall(MatProductSetFill(*D, fill));
10157 
10158     (*D)->product->api_user = PETSC_TRUE;
10159     PetscCall(MatProductSetFromOptions(*D));
10160     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,
10161                ((PetscObject)C)->type_name);
10162     PetscCall(MatProductSymbolic(*D));
10163   } else { /* user may change input matrices when REUSE */
10164     PetscCall(MatProductReplaceMats(A, B, C, *D));
10165   }
10166   PetscCall(MatProductNumeric(*D));
10167   PetscFunctionReturn(PETSC_SUCCESS);
10168 }
10169 
10170 /*@
10171    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10172 
10173    Collective
10174 
10175    Input Parameters:
10176 +  mat - the matrix
10177 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10178 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10179 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10180 
10181    Output Parameter:
10182 .  matredundant - redundant matrix
10183 
10184    Level: advanced
10185 
10186    Notes:
10187    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10188    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10189 
10190    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10191    calling it.
10192 
10193    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10194 
10195 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10196 @*/
10197 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10198 {
10199   MPI_Comm       comm;
10200   PetscMPIInt    size;
10201   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10202   Mat_Redundant *redund     = NULL;
10203   PetscSubcomm   psubcomm   = NULL;
10204   MPI_Comm       subcomm_in = subcomm;
10205   Mat           *matseq;
10206   IS             isrow, iscol;
10207   PetscBool      newsubcomm = PETSC_FALSE;
10208 
10209   PetscFunctionBegin;
10210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10211   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10212     PetscValidPointer(*matredundant, 5);
10213     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10214   }
10215 
10216   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10217   if (size == 1 || nsubcomm == 1) {
10218     if (reuse == MAT_INITIAL_MATRIX) {
10219       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10220     } else {
10221       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");
10222       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10223     }
10224     PetscFunctionReturn(PETSC_SUCCESS);
10225   }
10226 
10227   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10228   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10229   MatCheckPreallocated(mat, 1);
10230 
10231   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10232   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10233     /* create psubcomm, then get subcomm */
10234     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10235     PetscCallMPI(MPI_Comm_size(comm, &size));
10236     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10237 
10238     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10239     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10240     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10241     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10242     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10243     newsubcomm = PETSC_TRUE;
10244     PetscCall(PetscSubcommDestroy(&psubcomm));
10245   }
10246 
10247   /* get isrow, iscol and a local sequential matrix matseq[0] */
10248   if (reuse == MAT_INITIAL_MATRIX) {
10249     mloc_sub = PETSC_DECIDE;
10250     nloc_sub = PETSC_DECIDE;
10251     if (bs < 1) {
10252       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10253       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10254     } else {
10255       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10256       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10257     }
10258     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10259     rstart = rend - mloc_sub;
10260     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10261     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10262   } else { /* reuse == MAT_REUSE_MATRIX */
10263     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");
10264     /* retrieve subcomm */
10265     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10266     redund = (*matredundant)->redundant;
10267     isrow  = redund->isrow;
10268     iscol  = redund->iscol;
10269     matseq = redund->matseq;
10270   }
10271   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10272 
10273   /* get matredundant over subcomm */
10274   if (reuse == MAT_INITIAL_MATRIX) {
10275     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10276 
10277     /* create a supporting struct and attach it to C for reuse */
10278     PetscCall(PetscNew(&redund));
10279     (*matredundant)->redundant = redund;
10280     redund->isrow              = isrow;
10281     redund->iscol              = iscol;
10282     redund->matseq             = matseq;
10283     if (newsubcomm) {
10284       redund->subcomm = subcomm;
10285     } else {
10286       redund->subcomm = MPI_COMM_NULL;
10287     }
10288   } else {
10289     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10290   }
10291 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10292   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10293     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10294     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10295   }
10296 #endif
10297   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10298   PetscFunctionReturn(PETSC_SUCCESS);
10299 }
10300 
10301 /*@C
10302    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10303    a given `Mat`. Each submatrix can span multiple procs.
10304 
10305    Collective
10306 
10307    Input Parameters:
10308 +  mat - the matrix
10309 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10310 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10311 
10312    Output Parameter:
10313 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10314 
10315   Level: advanced
10316 
10317   Notes:
10318   The submatrix partition across processors is dictated by `subComm` a
10319   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10320   is not restricted to be grouped with consecutive original ranks.
10321 
10322   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10323   map directly to the layout of the original matrix [wrt the local
10324   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10325   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10326   the `subMat`. However the offDiagMat looses some columns - and this is
10327   reconstructed with `MatSetValues()`
10328 
10329   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10330 
10331 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10332 @*/
10333 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10334 {
10335   PetscMPIInt commsize, subCommSize;
10336 
10337   PetscFunctionBegin;
10338   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10339   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10340   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10341 
10342   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");
10343   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10344   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10345   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10346   PetscFunctionReturn(PETSC_SUCCESS);
10347 }
10348 
10349 /*@
10350    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10351 
10352    Not Collective
10353 
10354    Input Parameters:
10355 +  mat - matrix to extract local submatrix from
10356 .  isrow - local row indices for submatrix
10357 -  iscol - local column indices for submatrix
10358 
10359    Output Parameter:
10360 .  submat - the submatrix
10361 
10362    Level: intermediate
10363 
10364    Notes:
10365    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10366 
10367    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10368    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10369 
10370    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10371    `MatSetValuesBlockedLocal()` will also be implemented.
10372 
10373    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10374    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10375 
10376 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10377 @*/
10378 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10379 {
10380   PetscFunctionBegin;
10381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10382   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10383   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10384   PetscCheckSameComm(isrow, 2, iscol, 3);
10385   PetscValidPointer(submat, 4);
10386   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10387 
10388   if (mat->ops->getlocalsubmatrix) {
10389     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10390   } else {
10391     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10392   }
10393   PetscFunctionReturn(PETSC_SUCCESS);
10394 }
10395 
10396 /*@
10397    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10398 
10399    Not Collective
10400 
10401    Input Parameters:
10402 +  mat - matrix to extract local submatrix from
10403 .  isrow - local row indices for submatrix
10404 .  iscol - local column indices for submatrix
10405 -  submat - the submatrix
10406 
10407    Level: intermediate
10408 
10409 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10410 @*/
10411 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10412 {
10413   PetscFunctionBegin;
10414   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10415   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10416   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10417   PetscCheckSameComm(isrow, 2, iscol, 3);
10418   PetscValidPointer(submat, 4);
10419   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10420 
10421   if (mat->ops->restorelocalsubmatrix) {
10422     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10423   } else {
10424     PetscCall(MatDestroy(submat));
10425   }
10426   *submat = NULL;
10427   PetscFunctionReturn(PETSC_SUCCESS);
10428 }
10429 
10430 /*@
10431    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10432 
10433    Collective
10434 
10435    Input Parameter:
10436 .  mat - the matrix
10437 
10438    Output Parameter:
10439 .  is - if any rows have zero diagonals this contains the list of them
10440 
10441    Level: developer
10442 
10443 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10444 @*/
10445 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10446 {
10447   PetscFunctionBegin;
10448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10449   PetscValidType(mat, 1);
10450   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10451   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10452 
10453   if (!mat->ops->findzerodiagonals) {
10454     Vec                diag;
10455     const PetscScalar *a;
10456     PetscInt          *rows;
10457     PetscInt           rStart, rEnd, r, nrow = 0;
10458 
10459     PetscCall(MatCreateVecs(mat, &diag, NULL));
10460     PetscCall(MatGetDiagonal(mat, diag));
10461     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10462     PetscCall(VecGetArrayRead(diag, &a));
10463     for (r = 0; r < rEnd - rStart; ++r)
10464       if (a[r] == 0.0) ++nrow;
10465     PetscCall(PetscMalloc1(nrow, &rows));
10466     nrow = 0;
10467     for (r = 0; r < rEnd - rStart; ++r)
10468       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10469     PetscCall(VecRestoreArrayRead(diag, &a));
10470     PetscCall(VecDestroy(&diag));
10471     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10472   } else {
10473     PetscUseTypeMethod(mat, findzerodiagonals, is);
10474   }
10475   PetscFunctionReturn(PETSC_SUCCESS);
10476 }
10477 
10478 /*@
10479    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10480 
10481    Collective
10482 
10483    Input Parameter:
10484 .  mat - the matrix
10485 
10486    Output Parameter:
10487 .  is - contains the list of rows with off block diagonal entries
10488 
10489    Level: developer
10490 
10491 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10492 @*/
10493 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10494 {
10495   PetscFunctionBegin;
10496   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10497   PetscValidType(mat, 1);
10498   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10499   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10500 
10501   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10502   PetscFunctionReturn(PETSC_SUCCESS);
10503 }
10504 
10505 /*@C
10506   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10507 
10508   Collective; No Fortran Support
10509 
10510   Input Parameter:
10511 . mat - the matrix
10512 
10513   Output Parameter:
10514 . values - the block inverses in column major order (FORTRAN-like)
10515 
10516   Level: advanced
10517 
10518    Notes:
10519    The size of the blocks is determined by the block size of the matrix.
10520 
10521    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10522 
10523    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10524 
10525 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10526 @*/
10527 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10528 {
10529   PetscFunctionBegin;
10530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10531   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10532   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10533   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10534   PetscFunctionReturn(PETSC_SUCCESS);
10535 }
10536 
10537 /*@C
10538   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10539 
10540   Collective; No Fortran Support
10541 
10542   Input Parameters:
10543 + mat - the matrix
10544 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10545 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10546 
10547   Output Parameter:
10548 . values - the block inverses in column major order (FORTRAN-like)
10549 
10550   Level: advanced
10551 
10552   Notes:
10553   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10554 
10555   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10556 
10557 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10558 @*/
10559 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10560 {
10561   PetscFunctionBegin;
10562   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10563   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10564   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10565   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10566   PetscFunctionReturn(PETSC_SUCCESS);
10567 }
10568 
10569 /*@
10570   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10571 
10572   Collective
10573 
10574   Input Parameters:
10575 + A - the matrix
10576 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10577 
10578   Level: advanced
10579 
10580   Note:
10581   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10582 
10583 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10584 @*/
10585 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10586 {
10587   const PetscScalar *vals;
10588   PetscInt          *dnnz;
10589   PetscInt           m, rstart, rend, bs, i, j;
10590 
10591   PetscFunctionBegin;
10592   PetscCall(MatInvertBlockDiagonal(A, &vals));
10593   PetscCall(MatGetBlockSize(A, &bs));
10594   PetscCall(MatGetLocalSize(A, &m, NULL));
10595   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10596   PetscCall(PetscMalloc1(m / bs, &dnnz));
10597   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10598   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10599   PetscCall(PetscFree(dnnz));
10600   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10601   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10602   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10603   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10604   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10605   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10606   PetscFunctionReturn(PETSC_SUCCESS);
10607 }
10608 
10609 /*@C
10610     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10611     via `MatTransposeColoringCreate()`.
10612 
10613     Collective
10614 
10615     Input Parameter:
10616 .   c - coloring context
10617 
10618     Level: intermediate
10619 
10620 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10621 @*/
10622 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10623 {
10624   MatTransposeColoring matcolor = *c;
10625 
10626   PetscFunctionBegin;
10627   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10628   if (--((PetscObject)matcolor)->refct > 0) {
10629     matcolor = NULL;
10630     PetscFunctionReturn(PETSC_SUCCESS);
10631   }
10632 
10633   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10634   PetscCall(PetscFree(matcolor->rows));
10635   PetscCall(PetscFree(matcolor->den2sp));
10636   PetscCall(PetscFree(matcolor->colorforcol));
10637   PetscCall(PetscFree(matcolor->columns));
10638   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10639   PetscCall(PetscHeaderDestroy(c));
10640   PetscFunctionReturn(PETSC_SUCCESS);
10641 }
10642 
10643 /*@C
10644     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10645     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10646     `MatTransposeColoring` to sparse B.
10647 
10648     Collective
10649 
10650     Input Parameters:
10651 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10652 -   B - sparse matrix
10653 
10654     Output Parameter:
10655 .   Btdense - dense matrix B^T
10656 
10657     Level: developer
10658 
10659     Note:
10660     These are used internally for some implementations of `MatRARt()`
10661 
10662 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10663 @*/
10664 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10665 {
10666   PetscFunctionBegin;
10667   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10668   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10669   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10670 
10671   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10672   PetscFunctionReturn(PETSC_SUCCESS);
10673 }
10674 
10675 /*@C
10676     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10677     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10678     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10679     `Csp` from `Cden`.
10680 
10681     Collective
10682 
10683     Input Parameters:
10684 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10685 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10686 
10687     Output Parameter:
10688 .   Csp - sparse matrix
10689 
10690     Level: developer
10691 
10692     Note:
10693     These are used internally for some implementations of `MatRARt()`
10694 
10695 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10696 @*/
10697 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10698 {
10699   PetscFunctionBegin;
10700   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10701   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10702   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10703 
10704   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10705   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10706   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10707   PetscFunctionReturn(PETSC_SUCCESS);
10708 }
10709 
10710 /*@C
10711    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10712 
10713    Collective
10714 
10715    Input Parameters:
10716 +  mat - the matrix product C
10717 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10718 
10719     Output Parameter:
10720 .   color - the new coloring context
10721 
10722     Level: intermediate
10723 
10724 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10725           `MatTransColoringApplyDenToSp()`
10726 @*/
10727 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10728 {
10729   MatTransposeColoring c;
10730   MPI_Comm             comm;
10731 
10732   PetscFunctionBegin;
10733   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10734   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10735   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10736 
10737   c->ctype = iscoloring->ctype;
10738   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10739 
10740   *color = c;
10741   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10742   PetscFunctionReturn(PETSC_SUCCESS);
10743 }
10744 
10745 /*@
10746       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10747         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10748         same, otherwise it will be larger
10749 
10750      Not Collective
10751 
10752   Input Parameter:
10753 .    A  - the matrix
10754 
10755   Output Parameter:
10756 .    state - the current state
10757 
10758   Level: intermediate
10759 
10760   Notes:
10761     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10762          different matrices
10763 
10764     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10765 
10766     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10767 
10768 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10769 @*/
10770 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10771 {
10772   PetscFunctionBegin;
10773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10774   *state = mat->nonzerostate;
10775   PetscFunctionReturn(PETSC_SUCCESS);
10776 }
10777 
10778 /*@
10779       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10780                  matrices from each processor
10781 
10782     Collective
10783 
10784    Input Parameters:
10785 +    comm - the communicators the parallel matrix will live on
10786 .    seqmat - the input sequential matrices
10787 .    n - number of local columns (or `PETSC_DECIDE`)
10788 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10789 
10790    Output Parameter:
10791 .    mpimat - the parallel matrix generated
10792 
10793     Level: developer
10794 
10795    Note:
10796     The number of columns of the matrix in EACH processor MUST be the same.
10797 
10798 .seealso: [](chapter_matrices), `Mat`
10799 @*/
10800 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10801 {
10802   PetscMPIInt size;
10803 
10804   PetscFunctionBegin;
10805   PetscCallMPI(MPI_Comm_size(comm, &size));
10806   if (size == 1) {
10807     if (reuse == MAT_INITIAL_MATRIX) {
10808       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10809     } else {
10810       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10811     }
10812     PetscFunctionReturn(PETSC_SUCCESS);
10813   }
10814 
10815   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");
10816 
10817   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10818   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10819   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10820   PetscFunctionReturn(PETSC_SUCCESS);
10821 }
10822 
10823 /*@
10824      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10825 
10826     Collective
10827 
10828    Input Parameters:
10829 +    A   - the matrix to create subdomains from
10830 -    N   - requested number of subdomains
10831 
10832    Output Parameters:
10833 +    n   - number of subdomains resulting on this rank
10834 -    iss - `IS` list with indices of subdomains on this rank
10835 
10836     Level: advanced
10837 
10838     Note:
10839     The number of subdomains must be smaller than the communicator size
10840 
10841 .seealso: [](chapter_matrices), `Mat`, `IS`
10842 @*/
10843 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10844 {
10845   MPI_Comm    comm, subcomm;
10846   PetscMPIInt size, rank, color;
10847   PetscInt    rstart, rend, k;
10848 
10849   PetscFunctionBegin;
10850   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10851   PetscCallMPI(MPI_Comm_size(comm, &size));
10852   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10853   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);
10854   *n    = 1;
10855   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10856   color = rank / k;
10857   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10858   PetscCall(PetscMalloc1(1, iss));
10859   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10860   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10861   PetscCallMPI(MPI_Comm_free(&subcomm));
10862   PetscFunctionReturn(PETSC_SUCCESS);
10863 }
10864 
10865 /*@
10866    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10867 
10868    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10869    If they are not the same, uses `MatMatMatMult()`.
10870 
10871    Once the coarse grid problem is constructed, correct for interpolation operators
10872    that are not of full rank, which can legitimately happen in the case of non-nested
10873    geometric multigrid.
10874 
10875    Input Parameters:
10876 +  restrct - restriction operator
10877 .  dA - fine grid matrix
10878 .  interpolate - interpolation operator
10879 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10880 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10881 
10882    Output Parameter:
10883 .  A - the Galerkin coarse matrix
10884 
10885    Options Database Key:
10886 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10887 
10888    Level: developer
10889 
10890 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10891 @*/
10892 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10893 {
10894   IS  zerorows;
10895   Vec diag;
10896 
10897   PetscFunctionBegin;
10898   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10899   /* Construct the coarse grid matrix */
10900   if (interpolate == restrct) {
10901     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10902   } else {
10903     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10904   }
10905 
10906   /* If the interpolation matrix is not of full rank, A will have zero rows.
10907      This can legitimately happen in the case of non-nested geometric multigrid.
10908      In that event, we set the rows of the matrix to the rows of the identity,
10909      ignoring the equations (as the RHS will also be zero). */
10910 
10911   PetscCall(MatFindZeroRows(*A, &zerorows));
10912 
10913   if (zerorows != NULL) { /* if there are any zero rows */
10914     PetscCall(MatCreateVecs(*A, &diag, NULL));
10915     PetscCall(MatGetDiagonal(*A, diag));
10916     PetscCall(VecISSet(diag, zerorows, 1.0));
10917     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10918     PetscCall(VecDestroy(&diag));
10919     PetscCall(ISDestroy(&zerorows));
10920   }
10921   PetscFunctionReturn(PETSC_SUCCESS);
10922 }
10923 
10924 /*@C
10925     MatSetOperation - Allows user to set a matrix operation for any matrix type
10926 
10927    Logically Collective
10928 
10929     Input Parameters:
10930 +   mat - the matrix
10931 .   op - the name of the operation
10932 -   f - the function that provides the operation
10933 
10934    Level: developer
10935 
10936     Usage:
10937 .vb
10938   extern PetscErrorCode usermult(Mat, Vec, Vec);
10939 
10940   PetscCall(MatCreateXXX(comm, ..., &A));
10941   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10942 .ve
10943 
10944     Notes:
10945     See the file `include/petscmat.h` for a complete list of matrix
10946     operations, which all have the form MATOP_<OPERATION>, where
10947     <OPERATION> is the name (in all capital letters) of the
10948     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10949 
10950     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10951     sequence as the usual matrix interface routines, since they
10952     are intended to be accessed via the usual matrix interface
10953     routines, e.g.,
10954 .vb
10955   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10956 .ve
10957 
10958     In particular each function MUST return `PETSC_SUCCESS` on success and
10959     nonzero on failure.
10960 
10961     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10962 
10963 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10964 @*/
10965 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10966 {
10967   PetscFunctionBegin;
10968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10969   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10970   (((void (**)(void))mat->ops)[op]) = f;
10971   PetscFunctionReturn(PETSC_SUCCESS);
10972 }
10973 
10974 /*@C
10975     MatGetOperation - Gets a matrix operation for any matrix type.
10976 
10977     Not Collective
10978 
10979     Input Parameters:
10980 +   mat - the matrix
10981 -   op - the name of the operation
10982 
10983     Output Parameter:
10984 .   f - the function that provides the operation
10985 
10986     Level: developer
10987 
10988     Usage:
10989 .vb
10990       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10991       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10992 .ve
10993 
10994     Notes:
10995     See the file include/petscmat.h for a complete list of matrix
10996     operations, which all have the form MATOP_<OPERATION>, where
10997     <OPERATION> is the name (in all capital letters) of the
10998     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10999 
11000     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11001 
11002 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11003 @*/
11004 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11005 {
11006   PetscFunctionBegin;
11007   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11008   *f = (((void (**)(void))mat->ops)[op]);
11009   PetscFunctionReturn(PETSC_SUCCESS);
11010 }
11011 
11012 /*@
11013     MatHasOperation - Determines whether the given matrix supports the particular operation.
11014 
11015    Not Collective
11016 
11017    Input Parameters:
11018 +  mat - the matrix
11019 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11020 
11021    Output Parameter:
11022 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11023 
11024    Level: advanced
11025 
11026    Note:
11027    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11028 
11029 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11030 @*/
11031 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11032 {
11033   PetscFunctionBegin;
11034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11035   PetscValidBoolPointer(has, 3);
11036   if (mat->ops->hasoperation) {
11037     PetscUseTypeMethod(mat, hasoperation, op, has);
11038   } else {
11039     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11040     else {
11041       *has = PETSC_FALSE;
11042       if (op == MATOP_CREATE_SUBMATRIX) {
11043         PetscMPIInt size;
11044 
11045         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11046         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11047       }
11048     }
11049   }
11050   PetscFunctionReturn(PETSC_SUCCESS);
11051 }
11052 
11053 /*@
11054     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11055 
11056    Collective
11057 
11058    Input Parameter:
11059 .  mat - the matrix
11060 
11061    Output Parameter:
11062 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11063 
11064    Level: beginner
11065 
11066 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11067 @*/
11068 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11069 {
11070   PetscFunctionBegin;
11071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11072   PetscValidType(mat, 1);
11073   PetscValidBoolPointer(cong, 2);
11074   if (!mat->rmap || !mat->cmap) {
11075     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11076     PetscFunctionReturn(PETSC_SUCCESS);
11077   }
11078   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11079     PetscCall(PetscLayoutSetUp(mat->rmap));
11080     PetscCall(PetscLayoutSetUp(mat->cmap));
11081     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11082     if (*cong) mat->congruentlayouts = 1;
11083     else mat->congruentlayouts = 0;
11084   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11085   PetscFunctionReturn(PETSC_SUCCESS);
11086 }
11087 
11088 PetscErrorCode MatSetInf(Mat A)
11089 {
11090   PetscFunctionBegin;
11091   PetscUseTypeMethod(A, setinf);
11092   PetscFunctionReturn(PETSC_SUCCESS);
11093 }
11094 
11095 /*@C
11096    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
11097    and possibly removes small values from the graph structure.
11098 
11099    Collective
11100 
11101    Input Parameters:
11102 +  A - the matrix
11103 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11104 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11105 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11106 
11107    Output Parameter:
11108 .  graph - the resulting graph
11109 
11110    Level: advanced
11111 
11112 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11113 @*/
11114 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11115 {
11116   PetscFunctionBegin;
11117   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11118   PetscValidType(A, 1);
11119   PetscValidLogicalCollectiveBool(A, scale, 3);
11120   PetscValidPointer(graph, 5);
11121   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11122   PetscFunctionReturn(PETSC_SUCCESS);
11123 }
11124 
11125 /*@
11126   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11127   meaning the same memory is used for the matrix, and no new memory is allocated.
11128 
11129   Collective
11130 
11131   Input Parameter:
11132 . A - the matrix
11133 
11134   Level: intermediate
11135 
11136   Developer Note:
11137   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11138   of the arrays in the data structure are unneeded.
11139 
11140 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11141 @*/
11142 PetscErrorCode MatEliminateZeros(Mat A)
11143 {
11144   PetscFunctionBegin;
11145   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11146   PetscUseTypeMethod(A, eliminatezeros);
11147   PetscFunctionReturn(PETSC_SUCCESS);
11148 }
11149