xref: /petsc/src/mat/interface/matrix.c (revision 029efca733670abeac35b14fdbd8ea5bc1afb3ff)
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_DenseCopyToGPU, MAT_DenseCopyFromGPU;
42 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
43 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
44 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
45 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
46 
47 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
48 
49 /*@
50    MatSetRandom - Sets all components of a matrix to random numbers.
51 
52    Logically Collective
53 
54    Input Parameters:
55 +  x  - the matrix
56 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
57           it will create one internally.
58 
59    Example:
60 .vb
61      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
62      MatSetRandom(x,rctx);
63      PetscRandomDestroy(rctx);
64 .ve
65 
66    Level: intermediate
67 
68    Notes:
69    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
70 
71    for sparse matrices that already have locations it fills the locations with random numbers.
72 
73    It generates an error if used on sparse matrices that have not been preallocated.
74 
75 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
76 @*/
77 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
78 {
79   PetscRandom randObj = NULL;
80 
81   PetscFunctionBegin;
82   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
83   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
84   PetscValidType(x, 1);
85   MatCheckPreallocated(x, 1);
86 
87   if (!rctx) {
88     MPI_Comm comm;
89     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
90     PetscCall(PetscRandomCreate(comm, &randObj));
91     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
92     PetscCall(PetscRandomSetFromOptions(randObj));
93     rctx = randObj;
94   }
95   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
96   PetscUseTypeMethod(x, setrandom, rctx);
97   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
98 
99   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
100   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(PetscRandomDestroy(&randObj));
102   PetscFunctionReturn(PETSC_SUCCESS);
103 }
104 
105 /*@
106    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
107 
108    Logically Collective
109 
110    Input Parameter:
111 .  mat - the factored matrix
112 
113    Output Parameters:
114 +  pivot - the pivot value computed
115 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
116          the share the matrix
117 
118    Level: advanced
119 
120    Notes:
121     This routine does not work for factorizations done with external packages.
122 
123     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
124 
125     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
126 
127 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
128           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
129 @*/
130 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
131 {
132   PetscFunctionBegin;
133   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
134   PetscValidRealPointer(pivot, 2);
135   PetscValidIntPointer(row, 3);
136   *pivot = mat->factorerror_zeropivot_value;
137   *row   = mat->factorerror_zeropivot_row;
138   PetscFunctionReturn(PETSC_SUCCESS);
139 }
140 
141 /*@
142    MatFactorGetError - gets the error code from a factorization
143 
144    Logically Collective
145 
146    Input Parameter:
147 .  mat - the factored matrix
148 
149    Output Parameter:
150 .  err  - the error code
151 
152    Level: advanced
153 
154    Note:
155     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
156 
157 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
158           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
159 @*/
160 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
161 {
162   PetscFunctionBegin;
163   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
164   PetscValidPointer(err, 2);
165   *err = mat->factorerrortype;
166   PetscFunctionReturn(PETSC_SUCCESS);
167 }
168 
169 /*@
170    MatFactorClearError - clears the error code in a factorization
171 
172    Logically Collective
173 
174    Input Parameter:
175 .  mat - the factored matrix
176 
177    Level: developer
178 
179    Note:
180     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
181 
182 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
183           `MatGetErrorCode()`, `MatFactorError`
184 @*/
185 PetscErrorCode MatFactorClearError(Mat mat)
186 {
187   PetscFunctionBegin;
188   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
189   mat->factorerrortype             = MAT_FACTOR_NOERROR;
190   mat->factorerror_zeropivot_value = 0.0;
191   mat->factorerror_zeropivot_row   = 0;
192   PetscFunctionReturn(PETSC_SUCCESS);
193 }
194 
195 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
196 {
197   Vec                r, l;
198   const PetscScalar *al;
199   PetscInt           i, nz, gnz, N, n;
200 
201   PetscFunctionBegin;
202   PetscCall(MatCreateVecs(mat, &r, &l));
203   if (!cols) { /* nonzero rows */
204     PetscCall(MatGetSize(mat, &N, NULL));
205     PetscCall(MatGetLocalSize(mat, &n, NULL));
206     PetscCall(VecSet(l, 0.0));
207     PetscCall(VecSetRandom(r, NULL));
208     PetscCall(MatMult(mat, r, l));
209     PetscCall(VecGetArrayRead(l, &al));
210   } else { /* nonzero columns */
211     PetscCall(MatGetSize(mat, NULL, &N));
212     PetscCall(MatGetLocalSize(mat, NULL, &n));
213     PetscCall(VecSet(r, 0.0));
214     PetscCall(VecSetRandom(l, NULL));
215     PetscCall(MatMultTranspose(mat, l, r));
216     PetscCall(VecGetArrayRead(r, &al));
217   }
218   if (tol <= 0.0) {
219     for (i = 0, nz = 0; i < n; i++)
220       if (al[i] != 0.0) nz++;
221   } else {
222     for (i = 0, nz = 0; i < n; i++)
223       if (PetscAbsScalar(al[i]) > tol) nz++;
224   }
225   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
226   if (gnz != N) {
227     PetscInt *nzr;
228     PetscCall(PetscMalloc1(nz, &nzr));
229     if (nz) {
230       if (tol < 0) {
231         for (i = 0, nz = 0; i < n; i++)
232           if (al[i] != 0.0) nzr[nz++] = i;
233       } else {
234         for (i = 0, nz = 0; i < n; i++)
235           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
236       }
237     }
238     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
239   } else *nonzero = NULL;
240   if (!cols) { /* nonzero rows */
241     PetscCall(VecRestoreArrayRead(l, &al));
242   } else {
243     PetscCall(VecRestoreArrayRead(r, &al));
244   }
245   PetscCall(VecDestroy(&l));
246   PetscCall(VecDestroy(&r));
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249 
250 /*@
251       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
252 
253   Input Parameter:
254 .    A  - the matrix
255 
256   Output Parameter:
257 .    keptrows - the rows that are not completely zero
258 
259   Level: intermediate
260 
261   Note:
262     `keptrows` is set to `NULL` if all rows are nonzero.
263 
264 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
265  @*/
266 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
267 {
268   PetscFunctionBegin;
269   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
270   PetscValidType(mat, 1);
271   PetscValidPointer(keptrows, 2);
272   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
273   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
274   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
275   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
276   PetscFunctionReturn(PETSC_SUCCESS);
277 }
278 
279 /*@
280       MatFindZeroRows - Locate all rows that are completely zero in the matrix
281 
282   Input Parameter:
283 .    A  - the matrix
284 
285   Output Parameter:
286 .    zerorows - the rows that are completely zero
287 
288   Level: intermediate
289 
290   Note:
291     `zerorows` is set to `NULL` if no rows are zero.
292 
293 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
294  @*/
295 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
296 {
297   IS       keptrows;
298   PetscInt m, n;
299 
300   PetscFunctionBegin;
301   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
302   PetscValidType(mat, 1);
303   PetscValidPointer(zerorows, 2);
304   PetscCall(MatFindNonzeroRows(mat, &keptrows));
305   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
306      In keeping with this convention, we set zerorows to NULL if there are no zero
307      rows. */
308   if (keptrows == NULL) {
309     *zerorows = NULL;
310   } else {
311     PetscCall(MatGetOwnershipRange(mat, &m, &n));
312     PetscCall(ISComplement(keptrows, m, n, zerorows));
313     PetscCall(ISDestroy(&keptrows));
314   }
315   PetscFunctionReturn(PETSC_SUCCESS);
316 }
317 
318 /*@
319    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
320 
321    Not Collective
322 
323    Input Parameter:
324 .   A - the matrix
325 
326    Output Parameter:
327 .   a - the diagonal part (which is a SEQUENTIAL matrix)
328 
329    Level: advanced
330 
331    Notes:
332    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
333 
334    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
335 
336 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
337 @*/
338 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
339 {
340   PetscFunctionBegin;
341   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
342   PetscValidType(A, 1);
343   PetscValidPointer(a, 2);
344   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
345   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
346   else {
347     PetscMPIInt size;
348 
349     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
350     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
351     *a = A;
352   }
353   PetscFunctionReturn(PETSC_SUCCESS);
354 }
355 
356 /*@
357    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
358 
359    Collective
360 
361    Input Parameter:
362 .  mat - the matrix
363 
364    Output Parameter:
365 .   trace - the sum of the diagonal entries
366 
367    Level: advanced
368 
369 .seealso: [](ch_matrices), `Mat`
370 @*/
371 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
372 {
373   Vec diag;
374 
375   PetscFunctionBegin;
376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
377   PetscValidScalarPointer(trace, 2);
378   PetscCall(MatCreateVecs(mat, &diag, NULL));
379   PetscCall(MatGetDiagonal(mat, diag));
380   PetscCall(VecSum(diag, trace));
381   PetscCall(VecDestroy(&diag));
382   PetscFunctionReturn(PETSC_SUCCESS);
383 }
384 
385 /*@
386    MatRealPart - Zeros out the imaginary part of the matrix
387 
388    Logically Collective
389 
390    Input Parameter:
391 .  mat - the matrix
392 
393    Level: advanced
394 
395 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
396 @*/
397 PetscErrorCode MatRealPart(Mat mat)
398 {
399   PetscFunctionBegin;
400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
401   PetscValidType(mat, 1);
402   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
403   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
404   MatCheckPreallocated(mat, 1);
405   PetscUseTypeMethod(mat, realpart);
406   PetscFunctionReturn(PETSC_SUCCESS);
407 }
408 
409 /*@C
410    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
411 
412    Collective
413 
414    Input Parameter:
415 .  mat - the matrix
416 
417    Output Parameters:
418 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
419 -   ghosts - the global indices of the ghost points
420 
421    Level: advanced
422 
423    Note:
424    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
425 
426 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
427 @*/
428 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
429 {
430   PetscFunctionBegin;
431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
432   PetscValidType(mat, 1);
433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
435   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
436   else {
437     if (nghosts) *nghosts = 0;
438     if (ghosts) *ghosts = NULL;
439   }
440   PetscFunctionReturn(PETSC_SUCCESS);
441 }
442 
443 /*@
444    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
445 
446    Logically Collective
447 
448    Input Parameter:
449 .  mat - the matrix
450 
451    Level: advanced
452 
453 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
454 @*/
455 PetscErrorCode MatImaginaryPart(Mat mat)
456 {
457   PetscFunctionBegin;
458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
459   PetscValidType(mat, 1);
460   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
461   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
462   MatCheckPreallocated(mat, 1);
463   PetscUseTypeMethod(mat, imaginarypart);
464   PetscFunctionReturn(PETSC_SUCCESS);
465 }
466 
467 /*@
468    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
469 
470    Not Collective
471 
472    Input Parameter:
473 .  mat - the matrix
474 
475    Output Parameters:
476 +  missing - is any diagonal missing
477 -  dd - first diagonal entry that is missing (optional) on this process
478 
479    Level: advanced
480 
481 .seealso: [](ch_matrices), `Mat`
482 @*/
483 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
484 {
485   PetscFunctionBegin;
486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
487   PetscValidType(mat, 1);
488   PetscValidBoolPointer(missing, 2);
489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
491   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
492   PetscFunctionReturn(PETSC_SUCCESS);
493 }
494 
495 /*@C
496    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
497    for each row that you get to ensure that your application does
498    not bleed memory.
499 
500    Not Collective
501 
502    Input Parameters:
503 +  mat - the matrix
504 -  row - the row to get
505 
506    Output Parameters:
507 +  ncols -  if not `NULL`, the number of nonzeros in the row
508 .  cols - if not `NULL`, the column numbers
509 -  vals - if not `NULL`, the values
510 
511    Level: advanced
512 
513    Notes:
514    This routine is provided for people who need to have direct access
515    to the structure of a matrix.  We hope that we provide enough
516    high-level matrix routines that few users will need it.
517 
518    `MatGetRow()` always returns 0-based column indices, regardless of
519    whether the internal representation is 0-based (default) or 1-based.
520 
521    For better efficiency, set cols and/or vals to `NULL` if you do
522    not wish to extract these quantities.
523 
524    The user can only examine the values extracted with `MatGetRow()`;
525    the values cannot be altered.  To change the matrix entries, one
526    must use `MatSetValues()`.
527 
528    You can only have one call to `MatGetRow()` outstanding for a particular
529    matrix at a time, per processor. `MatGetRow()` can only obtain rows
530    associated with the given processor, it cannot get rows from the
531    other processors; for that we suggest using `MatCreateSubMatrices()`, then
532    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
533    is in the global number of rows.
534 
535    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
536 
537    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
538 
539    Fortran Note:
540    The calling sequence is
541 .vb
542    MatGetRow(matrix,row,ncols,cols,values,ierr)
543          Mat     matrix (input)
544          integer row    (input)
545          integer ncols  (output)
546          integer cols(maxcols) (output)
547          double precision (or double complex) values(maxcols) output
548 .ve
549    where maxcols >= maximum nonzeros in any row of the matrix.
550 
551    Caution:
552    Do not try to change the contents of the output arrays (`cols` and `vals`).
553    In some cases, this may corrupt the matrix.
554 
555 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
556 @*/
557 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
558 {
559   PetscInt incols;
560 
561   PetscFunctionBegin;
562   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
563   PetscValidType(mat, 1);
564   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
565   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
566   MatCheckPreallocated(mat, 1);
567   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);
568   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
569   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
570   if (ncols) *ncols = incols;
571   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
572   PetscFunctionReturn(PETSC_SUCCESS);
573 }
574 
575 /*@
576    MatConjugate - replaces the matrix values with their complex conjugates
577 
578    Logically Collective
579 
580    Input Parameter:
581 .  mat - the matrix
582 
583    Level: advanced
584 
585 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
586 @*/
587 PetscErrorCode MatConjugate(Mat mat)
588 {
589   PetscFunctionBegin;
590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
591   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
592   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
593     PetscUseTypeMethod(mat, conjugate);
594     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
595   }
596   PetscFunctionReturn(PETSC_SUCCESS);
597 }
598 
599 /*@C
600    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
601 
602    Not Collective
603 
604    Input Parameters:
605 +  mat - the matrix
606 .  row - the row to get
607 .  ncols - the number of nonzeros
608 .  cols - the columns of the nonzeros
609 -  vals - if nonzero the column values
610 
611    Level: advanced
612 
613    Notes:
614    This routine should be called after you have finished examining the entries.
615 
616    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
617    us of the array after it has been restored. If you pass `NULL`, it will
618    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
619 
620    Fortran Notes:
621    The calling sequence is
622 .vb
623    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
624       Mat     matrix (input)
625       integer row    (input)
626       integer ncols  (output)
627       integer cols(maxcols) (output)
628       double precision (or double complex) values(maxcols) output
629 .ve
630    Where maxcols >= maximum nonzeros in any row of the matrix.
631 
632    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
633    before another call to `MatGetRow()` can be made.
634 
635 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
636 @*/
637 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
638 {
639   PetscFunctionBegin;
640   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
641   if (ncols) PetscValidIntPointer(ncols, 3);
642   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
643   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
644   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
645   if (ncols) *ncols = 0;
646   if (cols) *cols = NULL;
647   if (vals) *vals = NULL;
648   PetscFunctionReturn(PETSC_SUCCESS);
649 }
650 
651 /*@
652    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
653    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
654 
655    Not Collective
656 
657    Input Parameter:
658 .  mat - the matrix
659 
660    Level: advanced
661 
662    Note:
663    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.
664 
665 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
666 @*/
667 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
668 {
669   PetscFunctionBegin;
670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
671   PetscValidType(mat, 1);
672   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
673   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
674   MatCheckPreallocated(mat, 1);
675   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
676   PetscUseTypeMethod(mat, getrowuppertriangular);
677   PetscFunctionReturn(PETSC_SUCCESS);
678 }
679 
680 /*@
681    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
682 
683    Not Collective
684 
685    Input Parameter:
686 .  mat - the matrix
687 
688    Level: advanced
689 
690    Note:
691    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
692 
693 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
694 @*/
695 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
696 {
697   PetscFunctionBegin;
698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
699   PetscValidType(mat, 1);
700   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
701   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
702   MatCheckPreallocated(mat, 1);
703   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
704   PetscUseTypeMethod(mat, restorerowuppertriangular);
705   PetscFunctionReturn(PETSC_SUCCESS);
706 }
707 
708 /*@C
709    MatSetOptionsPrefix - Sets the prefix used for searching for all
710    `Mat` options in the database.
711 
712    Logically Collective
713 
714    Input Parameters:
715 +  A - the matrix
716 -  prefix - the prefix to prepend to all option names
717 
718    Level: advanced
719 
720    Notes:
721    A hyphen (-) must NOT be given at the beginning of the prefix name.
722    The first character of all runtime options is AUTOMATICALLY the hyphen.
723 
724    This is NOT used for options for the factorization of the matrix. Normally the
725    prefix is automatically passed in from the PC calling the factorization. To set
726    it directly use  `MatSetOptionsPrefixFactor()`
727 
728 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
729 @*/
730 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
731 {
732   PetscFunctionBegin;
733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
734   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
735   PetscFunctionReturn(PETSC_SUCCESS);
736 }
737 
738 /*@C
739    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
740    for matrices created with `MatGetFactor()`
741 
742    Logically Collective
743 
744    Input Parameters:
745 +  A - the matrix
746 -  prefix - the prefix to prepend to all option names for the factored matrix
747 
748    Level: developer
749 
750    Notes:
751    A hyphen (-) must NOT be given at the beginning of the prefix name.
752    The first character of all runtime options is AUTOMATICALLY the hyphen.
753 
754    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
755    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
756 
757 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
758 @*/
759 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
760 {
761   PetscFunctionBegin;
762   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
763   if (prefix) {
764     PetscValidCharPointer(prefix, 2);
765     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
766     if (prefix != A->factorprefix) {
767       PetscCall(PetscFree(A->factorprefix));
768       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
769     }
770   } else PetscCall(PetscFree(A->factorprefix));
771   PetscFunctionReturn(PETSC_SUCCESS);
772 }
773 
774 /*@C
775    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
776    for matrices created with `MatGetFactor()`
777 
778    Logically Collective
779 
780    Input Parameters:
781 +  A - the matrix
782 -  prefix - the prefix to prepend to all option names for the factored matrix
783 
784    Level: developer
785 
786    Notes:
787    A hyphen (-) must NOT be given at the beginning of the prefix name.
788    The first character of all runtime options is AUTOMATICALLY the hyphen.
789 
790    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
791    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
792 
793 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
794           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
795           `MatSetOptionsPrefix()`
796 @*/
797 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
798 {
799   size_t len1, len2, new_len;
800 
801   PetscFunctionBegin;
802   PetscValidHeader(A, 1);
803   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
804   if (!A->factorprefix) {
805     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
806     PetscFunctionReturn(PETSC_SUCCESS);
807   }
808   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
809 
810   PetscCall(PetscStrlen(A->factorprefix, &len1));
811   PetscCall(PetscStrlen(prefix, &len2));
812   new_len = len1 + len2 + 1;
813   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
814   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
815   PetscFunctionReturn(PETSC_SUCCESS);
816 }
817 
818 /*@C
819    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
820    matrix options in the database.
821 
822    Logically Collective
823 
824    Input Parameters:
825 +  A - the matrix
826 -  prefix - the prefix to prepend to all option names
827 
828    Level: advanced
829 
830    Note:
831    A hyphen (-) must NOT be given at the beginning of the prefix name.
832    The first character of all runtime options is AUTOMATICALLY the hyphen.
833 
834 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
835 @*/
836 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
837 {
838   PetscFunctionBegin;
839   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
840   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
841   PetscFunctionReturn(PETSC_SUCCESS);
842 }
843 
844 /*@C
845    MatGetOptionsPrefix - Gets the prefix used for searching for all
846    matrix options in the database.
847 
848    Not Collective
849 
850    Input Parameter:
851 .  A - the matrix
852 
853    Output Parameter:
854 .  prefix - pointer to the prefix string used
855 
856    Level: advanced
857 
858    Fortran Note:
859    The user should pass in a string `prefix` of
860    sufficient length to hold the prefix.
861 
862 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
863 @*/
864 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
865 {
866   PetscFunctionBegin;
867   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
868   PetscValidPointer(prefix, 2);
869   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
870   PetscFunctionReturn(PETSC_SUCCESS);
871 }
872 
873 /*@
874    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
875 
876    Collective
877 
878    Input Parameter:
879 .  A - the matrix
880 
881    Level: beginner
882 
883    Notes:
884    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
885 
886    Users can reset the preallocation to access the original memory.
887 
888    Currently only supported for  `MATAIJ` matrices.
889 
890 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
891 @*/
892 PetscErrorCode MatResetPreallocation(Mat A)
893 {
894   PetscFunctionBegin;
895   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
896   PetscValidType(A, 1);
897   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
898   PetscFunctionReturn(PETSC_SUCCESS);
899 }
900 
901 /*@
902    MatSetUp - Sets up the internal matrix data structures for later use.
903 
904    Collective
905 
906    Input Parameter:
907 .  A - the matrix
908 
909    Level: intermediate
910 
911    Notes:
912    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
913    setting values in the matrix.
914 
915    If a suitable preallocation routine is used, this function does not need to be called.
916 
917    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
918 
919 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
920 @*/
921 PetscErrorCode MatSetUp(Mat A)
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
925   if (!((PetscObject)A)->type_name) {
926     PetscMPIInt size;
927 
928     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
929     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
930   }
931   if (!A->preallocated) PetscTryTypeMethod(A, setup);
932   PetscCall(PetscLayoutSetUp(A->rmap));
933   PetscCall(PetscLayoutSetUp(A->cmap));
934   A->preallocated = PETSC_TRUE;
935   PetscFunctionReturn(PETSC_SUCCESS);
936 }
937 
938 #if defined(PETSC_HAVE_SAWS)
939   #include <petscviewersaws.h>
940 #endif
941 
942 /*
943    If threadsafety is on extraneous matrices may be printed
944 
945    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
946 */
947 #if !defined(PETSC_HAVE_THREADSAFETY)
948 static PetscInt insidematview = 0;
949 #endif
950 
951 /*@C
952    MatViewFromOptions - View properties of the matrix based on options set in the options database
953 
954    Collective
955 
956    Input Parameters:
957 +  A - the matrix
958 .  obj - optional additional object that provides the options prefix to use
959 -  name - command line option
960 
961   Options Database Key:
962 .  -mat_view [viewertype]:... - the viewer and its options
963 
964    Level: intermediate
965 
966   Notes:
967 .vb
968     If no value is provided ascii:stdout is used
969        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
970                                                   for example ascii::ascii_info prints just the information about the object not all details
971                                                   unless :append is given filename opens in write mode, overwriting what was already there
972        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
973        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
974        socket[:port]                             defaults to the standard output port
975        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
976 .ve
977 
978 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
979 @*/
980 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
981 {
982   PetscFunctionBegin;
983   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
984 #if !defined(PETSC_HAVE_THREADSAFETY)
985   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
986 #endif
987   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
988   PetscFunctionReturn(PETSC_SUCCESS);
989 }
990 
991 /*@C
992    MatView - display information about a matrix in a variety ways
993 
994    Collective
995 
996    Input Parameters:
997 +  mat - the matrix
998 -  viewer - visualization context
999 
1000    Options Database Keys:
1001 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1002 .  -mat_view ::ascii_info_detail - Prints more detailed info
1003 .  -mat_view - Prints matrix in ASCII format
1004 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1005 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1006 .  -display <name> - Sets display name (default is host)
1007 .  -draw_pause <sec> - Sets number of seconds to pause after display
1008 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1009 .  -viewer_socket_machine <machine> -
1010 .  -viewer_socket_port <port> -
1011 .  -mat_view binary - save matrix to file in binary format
1012 -  -viewer_binary_filename <name> -
1013 
1014    Level: beginner
1015 
1016   Notes:
1017   The available visualization contexts include
1018 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1019 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1020 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1021 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1022 
1023    The user can open alternative visualization contexts with
1024 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1025 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1026          specified file; corresponding input uses MatLoad()
1027 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1028          an X window display
1029 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1030          Currently only the sequential dense and AIJ
1031          matrix types support the Socket viewer.
1032 
1033    The user can call `PetscViewerPushFormat()` to specify the output
1034    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1035    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1036 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1037 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1038 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1039 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1040          format common among all matrix types
1041 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1042          format (which is in many cases the same as the default)
1043 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1044          size and structure (not the matrix entries)
1045 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1046          the matrix structure
1047 
1048     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1049     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1050 
1051     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1052 
1053     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1054       viewer is used.
1055 
1056       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1057       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1058 
1059       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1060       and then use the following mouse functions.
1061 .vb
1062   left mouse: zoom in
1063   middle mouse: zoom out
1064   right mouse: continue with the simulation
1065 .ve
1066 
1067 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1068           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1069 @*/
1070 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1071 {
1072   PetscInt          rows, cols, rbs, cbs;
1073   PetscBool         isascii, isstring, issaws;
1074   PetscViewerFormat format;
1075   PetscMPIInt       size;
1076 
1077   PetscFunctionBegin;
1078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1079   PetscValidType(mat, 1);
1080   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1081   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1082   PetscCheckSameComm(mat, 1, viewer, 2);
1083 
1084   PetscCall(PetscViewerGetFormat(viewer, &format));
1085   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1086   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1087 
1088 #if !defined(PETSC_HAVE_THREADSAFETY)
1089   insidematview++;
1090 #endif
1091   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1092   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1093   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1094   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");
1095 
1096   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1097   if (isascii) {
1098     if (!mat->preallocated) {
1099       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1100 #if !defined(PETSC_HAVE_THREADSAFETY)
1101       insidematview--;
1102 #endif
1103       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1104       PetscFunctionReturn(PETSC_SUCCESS);
1105     }
1106     if (!mat->assembled) {
1107       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1108 #if !defined(PETSC_HAVE_THREADSAFETY)
1109       insidematview--;
1110 #endif
1111       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1112       PetscFunctionReturn(PETSC_SUCCESS);
1113     }
1114     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1115     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1116       MatNullSpace nullsp, transnullsp;
1117 
1118       PetscCall(PetscViewerASCIIPushTab(viewer));
1119       PetscCall(MatGetSize(mat, &rows, &cols));
1120       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1121       if (rbs != 1 || cbs != 1) {
1122         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1123         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1124       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1125       if (mat->factortype) {
1126         MatSolverType solver;
1127         PetscCall(MatFactorGetSolverType(mat, &solver));
1128         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1129       }
1130       if (mat->ops->getinfo) {
1131         MatInfo info;
1132         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1133         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1134         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1135       }
1136       PetscCall(MatGetNullSpace(mat, &nullsp));
1137       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1138       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1139       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1140       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1141       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1142       PetscCall(PetscViewerASCIIPushTab(viewer));
1143       PetscCall(MatProductView(mat, viewer));
1144       PetscCall(PetscViewerASCIIPopTab(viewer));
1145     }
1146   } else if (issaws) {
1147 #if defined(PETSC_HAVE_SAWS)
1148     PetscMPIInt rank;
1149 
1150     PetscCall(PetscObjectName((PetscObject)mat));
1151     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1152     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1153 #endif
1154   } else if (isstring) {
1155     const char *type;
1156     PetscCall(MatGetType(mat, &type));
1157     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1158     PetscTryTypeMethod(mat, view, viewer);
1159   }
1160   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1161     PetscCall(PetscViewerASCIIPushTab(viewer));
1162     PetscUseTypeMethod(mat, viewnative, viewer);
1163     PetscCall(PetscViewerASCIIPopTab(viewer));
1164   } else if (mat->ops->view) {
1165     PetscCall(PetscViewerASCIIPushTab(viewer));
1166     PetscUseTypeMethod(mat, view, viewer);
1167     PetscCall(PetscViewerASCIIPopTab(viewer));
1168   }
1169   if (isascii) {
1170     PetscCall(PetscViewerGetFormat(viewer, &format));
1171     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1172   }
1173   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1174 #if !defined(PETSC_HAVE_THREADSAFETY)
1175   insidematview--;
1176 #endif
1177   PetscFunctionReturn(PETSC_SUCCESS);
1178 }
1179 
1180 #if defined(PETSC_USE_DEBUG)
1181   #include <../src/sys/totalview/tv_data_display.h>
1182 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1183 {
1184   TV_add_row("Local rows", "int", &mat->rmap->n);
1185   TV_add_row("Local columns", "int", &mat->cmap->n);
1186   TV_add_row("Global rows", "int", &mat->rmap->N);
1187   TV_add_row("Global columns", "int", &mat->cmap->N);
1188   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1189   return TV_format_OK;
1190 }
1191 #endif
1192 
1193 /*@C
1194    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1195    with `MatView()`.  The matrix format is determined from the options database.
1196    Generates a parallel MPI matrix if the communicator has more than one
1197    processor.  The default matrix type is `MATAIJ`.
1198 
1199    Collective
1200 
1201    Input Parameters:
1202 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1203             or some related function before a call to `MatLoad()`
1204 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1205 
1206    Options Database Keys:
1207    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1208    block size
1209 .    -matload_block_size <bs> - set block size
1210 
1211    Level: beginner
1212 
1213    Notes:
1214    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1215    `Mat` before calling this routine if you wish to set it from the options database.
1216 
1217    `MatLoad()` automatically loads into the options database any options
1218    given in the file filename.info where filename is the name of the file
1219    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1220    file will be ignored if you use the -viewer_binary_skip_info option.
1221 
1222    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1223    sets the default matrix type AIJ and sets the local and global sizes.
1224    If type and/or size is already set, then the same are used.
1225 
1226    In parallel, each processor can load a subset of rows (or the
1227    entire matrix).  This routine is especially useful when a large
1228    matrix is stored on disk and only part of it is desired on each
1229    processor.  For example, a parallel solver may access only some of
1230    the rows from each processor.  The algorithm used here reads
1231    relatively small blocks of data rather than reading the entire
1232    matrix and then subsetting it.
1233 
1234    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1235    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1236    or the sequence like
1237 .vb
1238     `PetscViewer` v;
1239     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1240     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1241     `PetscViewerSetFromOptions`(v);
1242     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1243     `PetscViewerFileSetName`(v,"datafile");
1244 .ve
1245    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1246 $ -viewer_type {binary, hdf5}
1247 
1248    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1249    and src/mat/tutorials/ex10.c with the second approach.
1250 
1251    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1252    is read onto rank 0 and then shipped to its destination rank, one after another.
1253    Multiple objects, both matrices and vectors, can be stored within the same file.
1254    Their PetscObject name is ignored; they are loaded in the order of their storage.
1255 
1256    Most users should not need to know the details of the binary storage
1257    format, since `MatLoad()` and `MatView()` completely hide these details.
1258    But for anyone who's interested, the standard binary matrix storage
1259    format is
1260 
1261 .vb
1262     PetscInt    MAT_FILE_CLASSID
1263     PetscInt    number of rows
1264     PetscInt    number of columns
1265     PetscInt    total number of nonzeros
1266     PetscInt    *number nonzeros in each row
1267     PetscInt    *column indices of all nonzeros (starting index is zero)
1268     PetscScalar *values of all nonzeros
1269 .ve
1270 
1271    PETSc automatically does the byte swapping for
1272 machines that store the bytes reversed. Thus if you write your own binary
1273 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1274 and `PetscBinaryWrite()` to see how this may be done.
1275 
1276    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1277    Each processor's chunk is loaded independently by its owning rank.
1278    Multiple objects, both matrices and vectors, can be stored within the same file.
1279    They are looked up by their PetscObject name.
1280 
1281    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1282    by default the same structure and naming of the AIJ arrays and column count
1283    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1284 $    save example.mat A b -v7.3
1285    can be directly read by this routine (see Reference 1 for details).
1286 
1287    Depending on your MATLAB version, this format might be a default,
1288    otherwise you can set it as default in Preferences.
1289 
1290    Unless -nocompression flag is used to save the file in MATLAB,
1291    PETSc must be configured with ZLIB package.
1292 
1293    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1294 
1295    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1296 
1297    Corresponding `MatView()` is not yet implemented.
1298 
1299    The loaded matrix is actually a transpose of the original one in MATLAB,
1300    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1301    With this format, matrix is automatically transposed by PETSc,
1302    unless the matrix is marked as SPD or symmetric
1303    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1304 
1305    References:
1306 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1307 
1308 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1309  @*/
1310 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1311 {
1312   PetscBool flg;
1313 
1314   PetscFunctionBegin;
1315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1316   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1317 
1318   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1319 
1320   flg = PETSC_FALSE;
1321   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1322   if (flg) {
1323     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1324     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1325   }
1326   flg = PETSC_FALSE;
1327   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1328   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1329 
1330   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1331   PetscUseTypeMethod(mat, load, viewer);
1332   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1333   PetscFunctionReturn(PETSC_SUCCESS);
1334 }
1335 
1336 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1337 {
1338   Mat_Redundant *redund = *redundant;
1339 
1340   PetscFunctionBegin;
1341   if (redund) {
1342     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1343       PetscCall(ISDestroy(&redund->isrow));
1344       PetscCall(ISDestroy(&redund->iscol));
1345       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1346     } else {
1347       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1348       PetscCall(PetscFree(redund->sbuf_j));
1349       PetscCall(PetscFree(redund->sbuf_a));
1350       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1351         PetscCall(PetscFree(redund->rbuf_j[i]));
1352         PetscCall(PetscFree(redund->rbuf_a[i]));
1353       }
1354       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1355     }
1356 
1357     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1358     PetscCall(PetscFree(redund));
1359   }
1360   PetscFunctionReturn(PETSC_SUCCESS);
1361 }
1362 
1363 /*@C
1364    MatDestroy - Frees space taken by a matrix.
1365 
1366    Collective
1367 
1368    Input Parameter:
1369 .  A - the matrix
1370 
1371    Level: beginner
1372 
1373    Developer Note:
1374    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1375    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1376    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1377    if changes are needed here.
1378 
1379 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1380 @*/
1381 PetscErrorCode MatDestroy(Mat *A)
1382 {
1383   PetscFunctionBegin;
1384   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1385   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1386   if (--((PetscObject)(*A))->refct > 0) {
1387     *A = NULL;
1388     PetscFunctionReturn(PETSC_SUCCESS);
1389   }
1390 
1391   /* if memory was published with SAWs then destroy it */
1392   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1393   PetscTryTypeMethod((*A), destroy);
1394 
1395   PetscCall(PetscFree((*A)->factorprefix));
1396   PetscCall(PetscFree((*A)->defaultvectype));
1397   PetscCall(PetscFree((*A)->defaultrandtype));
1398   PetscCall(PetscFree((*A)->bsizes));
1399   PetscCall(PetscFree((*A)->solvertype));
1400   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1401   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1402   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1403   PetscCall(MatProductClear(*A));
1404   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1405   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1406   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1407   PetscCall(MatDestroy(&(*A)->schur));
1408   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1409   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1410   PetscCall(PetscHeaderDestroy(A));
1411   PetscFunctionReturn(PETSC_SUCCESS);
1412 }
1413 
1414 /*@C
1415    MatSetValues - Inserts or adds a block of values into a matrix.
1416    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1417    MUST be called after all calls to `MatSetValues()` have been completed.
1418 
1419    Not Collective
1420 
1421    Input Parameters:
1422 +  mat - the matrix
1423 .  v - a logically two-dimensional array of values
1424 .  m - the number of rows
1425 .  idxm - the global indices of the rows
1426 .  n - the number of columns
1427 .  idxn - the global indices of the columns
1428 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1429 
1430    Level: beginner
1431 
1432    Notes:
1433    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1434 
1435    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1436    options cannot be mixed without intervening calls to the assembly
1437    routines.
1438 
1439    `MatSetValues()` uses 0-based row and column numbers in Fortran
1440    as well as in C.
1441 
1442    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1443    simply ignored. This allows easily inserting element stiffness matrices
1444    with homogeneous Dirchlet boundary conditions that you don't want represented
1445    in the matrix.
1446 
1447    Efficiency Alert:
1448    The routine `MatSetValuesBlocked()` may offer much better efficiency
1449    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1450 
1451    Developer Note:
1452    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1453    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1454 
1455 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1456           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1457 @*/
1458 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1459 {
1460   PetscFunctionBeginHot;
1461   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1462   PetscValidType(mat, 1);
1463   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1464   PetscValidIntPointer(idxm, 3);
1465   PetscValidIntPointer(idxn, 5);
1466   MatCheckPreallocated(mat, 1);
1467 
1468   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1469   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1470 
1471   if (PetscDefined(USE_DEBUG)) {
1472     PetscInt i, j;
1473 
1474     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1475     for (i = 0; i < m; i++) {
1476       for (j = 0; j < n; j++) {
1477         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1478 #if defined(PETSC_USE_COMPLEX)
1479           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]);
1480 #else
1481           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]);
1482 #endif
1483       }
1484     }
1485     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);
1486     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);
1487   }
1488 
1489   if (mat->assembled) {
1490     mat->was_assembled = PETSC_TRUE;
1491     mat->assembled     = PETSC_FALSE;
1492   }
1493   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1494   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1495   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1496   PetscFunctionReturn(PETSC_SUCCESS);
1497 }
1498 
1499 /*@C
1500    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1501    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1502    MUST be called after all calls to `MatSetValues()` have been completed.
1503 
1504    Not Collective
1505 
1506    Input Parameters:
1507 +  mat - the matrix
1508 .  v - a logically two-dimensional array of values
1509 .  ism - the rows to provide
1510 .  isn - the columns to provide
1511 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1512 
1513    Level: beginner
1514 
1515    Notes:
1516    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1517 
1518    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1519    options cannot be mixed without intervening calls to the assembly
1520    routines.
1521 
1522    `MatSetValues()` uses 0-based row and column numbers in Fortran
1523    as well as in C.
1524 
1525    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1526    simply ignored. This allows easily inserting element stiffness matrices
1527    with homogeneous Dirchlet boundary conditions that you don't want represented
1528    in the matrix.
1529 
1530    Efficiency Alert:
1531    The routine `MatSetValuesBlocked()` may offer much better efficiency
1532    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1533 
1534     This is currently not optimized for any particular `ISType`
1535 
1536    Developer Notes:
1537     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1538                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1539 
1540 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1541           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1542 @*/
1543 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1544 {
1545   PetscInt        m, n;
1546   const PetscInt *rows, *cols;
1547 
1548   PetscFunctionBeginHot;
1549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1550   PetscCall(ISGetIndices(ism, &rows));
1551   PetscCall(ISGetIndices(isn, &cols));
1552   PetscCall(ISGetLocalSize(ism, &m));
1553   PetscCall(ISGetLocalSize(isn, &n));
1554   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1555   PetscCall(ISRestoreIndices(ism, &rows));
1556   PetscCall(ISRestoreIndices(isn, &cols));
1557   PetscFunctionReturn(PETSC_SUCCESS);
1558 }
1559 
1560 /*@
1561    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1562         values into a matrix
1563 
1564    Not Collective
1565 
1566    Input Parameters:
1567 +  mat - the matrix
1568 .  row - the (block) row to set
1569 -  v - a logically two-dimensional array of values
1570 
1571    Level: intermediate
1572 
1573    Notes:
1574    The values, `v`, are column-oriented (for the block version) and sorted
1575 
1576    All the nonzeros in the row must be provided
1577 
1578    The matrix must have previously had its column indices set, likely by having been assembled.
1579 
1580    The row must belong to this process
1581 
1582 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1583           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1584 @*/
1585 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1586 {
1587   PetscInt globalrow;
1588 
1589   PetscFunctionBegin;
1590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1591   PetscValidType(mat, 1);
1592   PetscValidScalarPointer(v, 3);
1593   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1594   PetscCall(MatSetValuesRow(mat, globalrow, v));
1595   PetscFunctionReturn(PETSC_SUCCESS);
1596 }
1597 
1598 /*@
1599    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1600         values into a matrix
1601 
1602    Not Collective
1603 
1604    Input Parameters:
1605 +  mat - the matrix
1606 .  row - the (block) row to set
1607 -  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
1608 
1609    Level: advanced
1610 
1611    Notes:
1612    The values, `v`, are column-oriented for the block version.
1613 
1614    All the nonzeros in the row must be provided
1615 
1616    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1617 
1618    The row must belong to this process
1619 
1620 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1621           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1622 @*/
1623 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1624 {
1625   PetscFunctionBeginHot;
1626   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1627   PetscValidType(mat, 1);
1628   MatCheckPreallocated(mat, 1);
1629   PetscValidScalarPointer(v, 3);
1630   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1631   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1632   mat->insertmode = INSERT_VALUES;
1633 
1634   if (mat->assembled) {
1635     mat->was_assembled = PETSC_TRUE;
1636     mat->assembled     = PETSC_FALSE;
1637   }
1638   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1639   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1640   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1641   PetscFunctionReturn(PETSC_SUCCESS);
1642 }
1643 
1644 /*@
1645    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1646      Using structured grid indexing
1647 
1648    Not Collective
1649 
1650    Input Parameters:
1651 +  mat - the matrix
1652 .  m - number of rows being entered
1653 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1654 .  n - number of columns being entered
1655 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1656 .  v - a logically two-dimensional array of values
1657 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1658 
1659    Level: beginner
1660 
1661    Notes:
1662    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1663 
1664    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1665    options cannot be mixed without intervening calls to the assembly
1666    routines.
1667 
1668    The grid coordinates are across the entire grid, not just the local portion
1669 
1670    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1671    as well as in C.
1672 
1673    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1674 
1675    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1676    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1677 
1678    The columns and rows in the stencil passed in MUST be contained within the
1679    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1680    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1681    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1682    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1683 
1684    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1685    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1686    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1687    `DM_BOUNDARY_PERIODIC` boundary type.
1688 
1689    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
1690    a single value per point) you can skip filling those indices.
1691 
1692    Inspired by the structured grid interface to the HYPRE package
1693    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1694 
1695    Efficiency Alert:
1696    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1697    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1698 
1699    Fortran Note:
1700    `idxm` and `idxn` should be declared as
1701 $     MatStencil idxm(4,m),idxn(4,n)
1702    and the values inserted using
1703 .vb
1704     idxm(MatStencil_i,1) = i
1705     idxm(MatStencil_j,1) = j
1706     idxm(MatStencil_k,1) = k
1707     idxm(MatStencil_c,1) = c
1708     etc
1709 .ve
1710 
1711 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1712           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1713 @*/
1714 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1715 {
1716   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1717   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1718   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1719 
1720   PetscFunctionBegin;
1721   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1723   PetscValidType(mat, 1);
1724   PetscValidPointer(idxm, 3);
1725   PetscValidPointer(idxn, 5);
1726 
1727   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1728     jdxm = buf;
1729     jdxn = buf + m;
1730   } else {
1731     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1732     jdxm = bufm;
1733     jdxn = bufn;
1734   }
1735   for (i = 0; i < m; i++) {
1736     for (j = 0; j < 3 - sdim; j++) dxm++;
1737     tmp = *dxm++ - starts[0];
1738     for (j = 0; j < dim - 1; j++) {
1739       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1740       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1741     }
1742     if (mat->stencil.noc) dxm++;
1743     jdxm[i] = tmp;
1744   }
1745   for (i = 0; i < n; i++) {
1746     for (j = 0; j < 3 - sdim; j++) dxn++;
1747     tmp = *dxn++ - starts[0];
1748     for (j = 0; j < dim - 1; j++) {
1749       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1750       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1751     }
1752     if (mat->stencil.noc) dxn++;
1753     jdxn[i] = tmp;
1754   }
1755   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1756   PetscCall(PetscFree2(bufm, bufn));
1757   PetscFunctionReturn(PETSC_SUCCESS);
1758 }
1759 
1760 /*@
1761    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1762      Using structured grid indexing
1763 
1764    Not Collective
1765 
1766    Input Parameters:
1767 +  mat - the matrix
1768 .  m - number of rows being entered
1769 .  idxm - grid coordinates for matrix rows being entered
1770 .  n - number of columns being entered
1771 .  idxn - grid coordinates for matrix columns being entered
1772 .  v - a logically two-dimensional array of values
1773 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1774 
1775    Level: beginner
1776 
1777    Notes:
1778    By default the values, `v`, are row-oriented and unsorted.
1779    See `MatSetOption()` for other options.
1780 
1781    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1782    options cannot be mixed without intervening calls to the assembly
1783    routines.
1784 
1785    The grid coordinates are across the entire grid, not just the local portion
1786 
1787    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1788    as well as in C.
1789 
1790    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1791 
1792    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1793    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1794 
1795    The columns and rows in the stencil passed in MUST be contained within the
1796    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1797    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1798    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1799    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1800 
1801    Negative indices may be passed in idxm and idxn, these rows and columns are
1802    simply ignored. This allows easily inserting element stiffness matrices
1803    with homogeneous Dirchlet boundary conditions that you don't want represented
1804    in the matrix.
1805 
1806    Inspired by the structured grid interface to the HYPRE package
1807    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1808 
1809    Fortran Note:
1810    `idxm` and `idxn` should be declared as
1811 $     MatStencil idxm(4,m),idxn(4,n)
1812    and the values inserted using
1813 .vb
1814     idxm(MatStencil_i,1) = i
1815     idxm(MatStencil_j,1) = j
1816     idxm(MatStencil_k,1) = k
1817    etc
1818 .ve
1819 
1820 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1821           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1822           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1823 @*/
1824 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1825 {
1826   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1827   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1828   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1829 
1830   PetscFunctionBegin;
1831   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1833   PetscValidType(mat, 1);
1834   PetscValidPointer(idxm, 3);
1835   PetscValidPointer(idxn, 5);
1836   PetscValidScalarPointer(v, 6);
1837 
1838   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1839     jdxm = buf;
1840     jdxn = buf + m;
1841   } else {
1842     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1843     jdxm = bufm;
1844     jdxn = bufn;
1845   }
1846   for (i = 0; i < m; i++) {
1847     for (j = 0; j < 3 - sdim; j++) dxm++;
1848     tmp = *dxm++ - starts[0];
1849     for (j = 0; j < sdim - 1; j++) {
1850       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1851       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1852     }
1853     dxm++;
1854     jdxm[i] = tmp;
1855   }
1856   for (i = 0; i < n; i++) {
1857     for (j = 0; j < 3 - sdim; j++) dxn++;
1858     tmp = *dxn++ - starts[0];
1859     for (j = 0; j < sdim - 1; j++) {
1860       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1861       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1862     }
1863     dxn++;
1864     jdxn[i] = tmp;
1865   }
1866   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1867   PetscCall(PetscFree2(bufm, bufn));
1868   PetscFunctionReturn(PETSC_SUCCESS);
1869 }
1870 
1871 /*@
1872    MatSetStencil - Sets the grid information for setting values into a matrix via
1873         `MatSetValuesStencil()`
1874 
1875    Not Collective
1876 
1877    Input Parameters:
1878 +  mat - the matrix
1879 .  dim - dimension of the grid 1, 2, or 3
1880 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1881 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1882 -  dof - number of degrees of freedom per node
1883 
1884    Level: beginner
1885 
1886    Notes:
1887    Inspired by the structured grid interface to the HYPRE package
1888    (www.llnl.gov/CASC/hyper)
1889 
1890    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1891    user.
1892 
1893 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1894           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1895 @*/
1896 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1897 {
1898   PetscFunctionBegin;
1899   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1900   PetscValidIntPointer(dims, 3);
1901   PetscValidIntPointer(starts, 4);
1902 
1903   mat->stencil.dim = dim + (dof > 1);
1904   for (PetscInt i = 0; i < dim; i++) {
1905     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1906     mat->stencil.starts[i] = starts[dim - i - 1];
1907   }
1908   mat->stencil.dims[dim]   = dof;
1909   mat->stencil.starts[dim] = 0;
1910   mat->stencil.noc         = (PetscBool)(dof == 1);
1911   PetscFunctionReturn(PETSC_SUCCESS);
1912 }
1913 
1914 /*@C
1915    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1916 
1917    Not Collective
1918 
1919    Input Parameters:
1920 +  mat - the matrix
1921 .  v - a logically two-dimensional array of values
1922 .  m  - the number of block rows
1923 .  idxm - the global block indices
1924 .  n - the number of block columns
1925 .  idxn - the global block indices
1926 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1927 
1928    Level: intermediate
1929 
1930    Notes:
1931    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1932    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1933 
1934    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1935    NOT the total number of rows/columns; for example, if the block size is 2 and
1936    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1937    The values in idxm would be 1 2; that is the first index for each block divided by
1938    the block size.
1939 
1940    You must call `MatSetBlockSize()` when constructing this matrix (before
1941    preallocating it).
1942 
1943    By default the values, `v`, are row-oriented, so the layout of
1944    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1945 
1946    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1947    options cannot be mixed without intervening calls to the assembly
1948    routines.
1949 
1950    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1951    as well as in C.
1952 
1953    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1954    simply ignored. This allows easily inserting element stiffness matrices
1955    with homogeneous Dirchlet boundary conditions that you don't want represented
1956    in the matrix.
1957 
1958    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1959    internal searching must be done to determine where to place the
1960    data in the matrix storage space.  By instead inserting blocks of
1961    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1962    reduced.
1963 
1964    Example:
1965 .vb
1966    Suppose m=n=2 and block size(bs) = 2 The array is
1967 
1968    1  2  | 3  4
1969    5  6  | 7  8
1970    - - - | - - -
1971    9  10 | 11 12
1972    13 14 | 15 16
1973 
1974    v[] should be passed in like
1975    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1976 
1977   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1978    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1979 .ve
1980 
1981 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1982 @*/
1983 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1984 {
1985   PetscFunctionBeginHot;
1986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1987   PetscValidType(mat, 1);
1988   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1989   PetscValidIntPointer(idxm, 3);
1990   PetscValidIntPointer(idxn, 5);
1991   MatCheckPreallocated(mat, 1);
1992   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1993   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1994   if (PetscDefined(USE_DEBUG)) {
1995     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1996     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1997   }
1998   if (PetscDefined(USE_DEBUG)) {
1999     PetscInt rbs, cbs, M, N, i;
2000     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2001     PetscCall(MatGetSize(mat, &M, &N));
2002     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);
2003     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);
2004   }
2005   if (mat->assembled) {
2006     mat->was_assembled = PETSC_TRUE;
2007     mat->assembled     = PETSC_FALSE;
2008   }
2009   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2010   if (mat->ops->setvaluesblocked) {
2011     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2012   } else {
2013     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2014     PetscInt i, j, bs, cbs;
2015 
2016     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2017     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2018       iidxm = buf;
2019       iidxn = buf + m * bs;
2020     } else {
2021       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2022       iidxm = bufr;
2023       iidxn = bufc;
2024     }
2025     for (i = 0; i < m; i++) {
2026       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2027     }
2028     if (m != n || bs != cbs || idxm != idxn) {
2029       for (i = 0; i < n; i++) {
2030         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2031       }
2032     } else iidxn = iidxm;
2033     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2034     PetscCall(PetscFree2(bufr, bufc));
2035   }
2036   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2037   PetscFunctionReturn(PETSC_SUCCESS);
2038 }
2039 
2040 /*@C
2041    MatGetValues - Gets a block of local values from a matrix.
2042 
2043    Not Collective; can only return values that are owned by the give process
2044 
2045    Input Parameters:
2046 +  mat - the matrix
2047 .  v - a logically two-dimensional array for storing the values
2048 .  m  - the number of rows
2049 .  idxm - the  global indices of the rows
2050 .  n - the number of columns
2051 -  idxn - the global indices of the columns
2052 
2053    Level: advanced
2054 
2055    Notes:
2056      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2057      The values, `v`, are then returned in a row-oriented format,
2058      analogous to that used by default in `MatSetValues()`.
2059 
2060      `MatGetValues()` uses 0-based row and column numbers in
2061      Fortran as well as in C.
2062 
2063      `MatGetValues()` requires that the matrix has been assembled
2064      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2065      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2066      without intermediate matrix assembly.
2067 
2068      Negative row or column indices will be ignored and those locations in `v` will be
2069      left unchanged.
2070 
2071      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2072      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2073      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2074 
2075 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2076 @*/
2077 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2078 {
2079   PetscFunctionBegin;
2080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2081   PetscValidType(mat, 1);
2082   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2083   PetscValidIntPointer(idxm, 3);
2084   PetscValidIntPointer(idxn, 5);
2085   PetscValidScalarPointer(v, 6);
2086   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2087   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2088   MatCheckPreallocated(mat, 1);
2089 
2090   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2091   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2092   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2093   PetscFunctionReturn(PETSC_SUCCESS);
2094 }
2095 
2096 /*@C
2097    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2098      defined previously by `MatSetLocalToGlobalMapping()`
2099 
2100    Not Collective
2101 
2102    Input Parameters:
2103 +  mat - the matrix
2104 .  nrow - number of rows
2105 .  irow - the row local indices
2106 .  ncol - number of columns
2107 -  icol - the column local indices
2108 
2109    Output Parameter:
2110 .  y -  a logically two-dimensional array of values
2111 
2112    Level: advanced
2113 
2114    Notes:
2115      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2116 
2117      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,
2118      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2119      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2120      with `MatSetLocalToGlobalMapping()`.
2121 
2122    Developer Note:
2123       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2124       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2125 
2126 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2127           `MatSetValuesLocal()`, `MatGetValues()`
2128 @*/
2129 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2130 {
2131   PetscFunctionBeginHot;
2132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2133   PetscValidType(mat, 1);
2134   MatCheckPreallocated(mat, 1);
2135   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2136   PetscValidIntPointer(irow, 3);
2137   PetscValidIntPointer(icol, 5);
2138   if (PetscDefined(USE_DEBUG)) {
2139     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2140     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2141   }
2142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2143   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2144   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2145   else {
2146     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2147     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2148       irowm = buf;
2149       icolm = buf + nrow;
2150     } else {
2151       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2152       irowm = bufr;
2153       icolm = bufc;
2154     }
2155     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2156     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2157     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2158     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2159     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2160     PetscCall(PetscFree2(bufr, bufc));
2161   }
2162   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2163   PetscFunctionReturn(PETSC_SUCCESS);
2164 }
2165 
2166 /*@
2167   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2168   the same size. Currently, this can only be called once and creates the given matrix.
2169 
2170   Not Collective
2171 
2172   Input Parameters:
2173 + mat - the matrix
2174 . nb - the number of blocks
2175 . bs - the number of rows (and columns) in each block
2176 . rows - a concatenation of the rows for each block
2177 - v - a concatenation of logically two-dimensional arrays of values
2178 
2179   Level: advanced
2180 
2181   Note:
2182   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2183 
2184   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2185 
2186 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2187           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2188 @*/
2189 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2190 {
2191   PetscFunctionBegin;
2192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2193   PetscValidType(mat, 1);
2194   PetscValidIntPointer(rows, 4);
2195   PetscValidScalarPointer(v, 5);
2196   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2197 
2198   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2199   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2200   else {
2201     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2202   }
2203   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2204   PetscFunctionReturn(PETSC_SUCCESS);
2205 }
2206 
2207 /*@
2208    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2209    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2210    using a local (per-processor) numbering.
2211 
2212    Not Collective
2213 
2214    Input Parameters:
2215 +  x - the matrix
2216 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2217 -  cmapping - column mapping
2218 
2219    Level: intermediate
2220 
2221    Note:
2222    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2223 
2224 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2225 @*/
2226 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2227 {
2228   PetscFunctionBegin;
2229   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2230   PetscValidType(x, 1);
2231   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2232   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2233   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2234   else {
2235     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2236     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2237   }
2238   PetscFunctionReturn(PETSC_SUCCESS);
2239 }
2240 
2241 /*@
2242    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2243 
2244    Not Collective
2245 
2246    Input Parameter:
2247 .  A - the matrix
2248 
2249    Output Parameters:
2250 + rmapping - row mapping
2251 - cmapping - column mapping
2252 
2253    Level: advanced
2254 
2255 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2256 @*/
2257 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2258 {
2259   PetscFunctionBegin;
2260   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2261   PetscValidType(A, 1);
2262   if (rmapping) {
2263     PetscValidPointer(rmapping, 2);
2264     *rmapping = A->rmap->mapping;
2265   }
2266   if (cmapping) {
2267     PetscValidPointer(cmapping, 3);
2268     *cmapping = A->cmap->mapping;
2269   }
2270   PetscFunctionReturn(PETSC_SUCCESS);
2271 }
2272 
2273 /*@
2274    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2275 
2276    Logically Collective
2277 
2278    Input Parameters:
2279 +  A - the matrix
2280 . rmap - row layout
2281 - cmap - column layout
2282 
2283    Level: advanced
2284 
2285    Note:
2286    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2287 
2288 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2289 @*/
2290 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2291 {
2292   PetscFunctionBegin;
2293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2294   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2295   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2296   PetscFunctionReturn(PETSC_SUCCESS);
2297 }
2298 
2299 /*@
2300    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2301 
2302    Not Collective
2303 
2304    Input Parameter:
2305 .  A - the matrix
2306 
2307    Output Parameters:
2308 + rmap - row layout
2309 - cmap - column layout
2310 
2311    Level: advanced
2312 
2313 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2314 @*/
2315 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2316 {
2317   PetscFunctionBegin;
2318   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2319   PetscValidType(A, 1);
2320   if (rmap) {
2321     PetscValidPointer(rmap, 2);
2322     *rmap = A->rmap;
2323   }
2324   if (cmap) {
2325     PetscValidPointer(cmap, 3);
2326     *cmap = A->cmap;
2327   }
2328   PetscFunctionReturn(PETSC_SUCCESS);
2329 }
2330 
2331 /*@C
2332    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2333    using a local numbering of the nodes.
2334 
2335    Not Collective
2336 
2337    Input Parameters:
2338 +  mat - the matrix
2339 .  nrow - number of rows
2340 .  irow - the row local indices
2341 .  ncol - number of columns
2342 .  icol - the column local indices
2343 .  y -  a logically two-dimensional array of values
2344 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2345 
2346    Level: intermediate
2347 
2348    Notes:
2349    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2350       `MatSetUp()` before using this routine
2351 
2352    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2353 
2354    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2355    options cannot be mixed without intervening calls to the assembly
2356    routines.
2357 
2358    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2359    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2360 
2361    Developer Note:
2362     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2363                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2364 
2365 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2366           `MatGetValuesLocal()`
2367 @*/
2368 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2369 {
2370   PetscFunctionBeginHot;
2371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2372   PetscValidType(mat, 1);
2373   MatCheckPreallocated(mat, 1);
2374   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2375   PetscValidIntPointer(irow, 3);
2376   PetscValidIntPointer(icol, 5);
2377   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2378   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2379   if (PetscDefined(USE_DEBUG)) {
2380     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2381     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2382   }
2383 
2384   if (mat->assembled) {
2385     mat->was_assembled = PETSC_TRUE;
2386     mat->assembled     = PETSC_FALSE;
2387   }
2388   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2389   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2390   else {
2391     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2392     const PetscInt *irowm, *icolm;
2393 
2394     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2395       bufr  = buf;
2396       bufc  = buf + nrow;
2397       irowm = bufr;
2398       icolm = bufc;
2399     } else {
2400       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2401       irowm = bufr;
2402       icolm = bufc;
2403     }
2404     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2405     else irowm = irow;
2406     if (mat->cmap->mapping) {
2407       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2408         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2409       } else icolm = irowm;
2410     } else icolm = icol;
2411     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2412     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2413   }
2414   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2415   PetscFunctionReturn(PETSC_SUCCESS);
2416 }
2417 
2418 /*@C
2419    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2420    using a local ordering of the nodes a block at a time.
2421 
2422    Not Collective
2423 
2424    Input Parameters:
2425 +  x - the matrix
2426 .  nrow - number of rows
2427 .  irow - the row local indices
2428 .  ncol - number of columns
2429 .  icol - the column local indices
2430 .  y -  a logically two-dimensional array of values
2431 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2432 
2433    Level: intermediate
2434 
2435    Notes:
2436    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2437       `MatSetUp()` before using this routine
2438 
2439    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2440       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2441 
2442    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2443    options cannot be mixed without intervening calls to the assembly
2444    routines.
2445 
2446    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2447    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2448 
2449    Developer Note:
2450     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2451                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2452 
2453 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2454           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2455 @*/
2456 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2457 {
2458   PetscFunctionBeginHot;
2459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2460   PetscValidType(mat, 1);
2461   MatCheckPreallocated(mat, 1);
2462   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2463   PetscValidIntPointer(irow, 3);
2464   PetscValidIntPointer(icol, 5);
2465   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2466   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2467   if (PetscDefined(USE_DEBUG)) {
2468     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2469     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);
2470   }
2471 
2472   if (mat->assembled) {
2473     mat->was_assembled = PETSC_TRUE;
2474     mat->assembled     = PETSC_FALSE;
2475   }
2476   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2477     PetscInt irbs, rbs;
2478     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2479     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2480     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2481   }
2482   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2483     PetscInt icbs, cbs;
2484     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2485     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2486     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2487   }
2488   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2489   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2490   else {
2491     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2492     const PetscInt *irowm, *icolm;
2493 
2494     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2495       bufr  = buf;
2496       bufc  = buf + nrow;
2497       irowm = bufr;
2498       icolm = bufc;
2499     } else {
2500       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2501       irowm = bufr;
2502       icolm = bufc;
2503     }
2504     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2505     else irowm = irow;
2506     if (mat->cmap->mapping) {
2507       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2508         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2509       } else icolm = irowm;
2510     } else icolm = icol;
2511     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2512     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2513   }
2514   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2515   PetscFunctionReturn(PETSC_SUCCESS);
2516 }
2517 
2518 /*@
2519    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2520 
2521    Collective
2522 
2523    Input Parameters:
2524 +  mat - the matrix
2525 -  x   - the vector to be multiplied
2526 
2527    Output Parameter:
2528 .  y - the result
2529 
2530    Level: developer
2531 
2532    Note:
2533    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2534    call `MatMultDiagonalBlock`(A,y,y).
2535 
2536 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2537 @*/
2538 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2539 {
2540   PetscFunctionBegin;
2541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2542   PetscValidType(mat, 1);
2543   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2544   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2545 
2546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2547   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2548   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2549   MatCheckPreallocated(mat, 1);
2550 
2551   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2552   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2553   PetscFunctionReturn(PETSC_SUCCESS);
2554 }
2555 
2556 /*@
2557    MatMult - Computes the matrix-vector product, y = Ax.
2558 
2559    Neighbor-wise Collective
2560 
2561    Input Parameters:
2562 +  mat - the matrix
2563 -  x   - the vector to be multiplied
2564 
2565    Output Parameter:
2566 .  y - the result
2567 
2568    Level: beginner
2569 
2570    Note:
2571    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2572    call `MatMult`(A,y,y).
2573 
2574 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2575 @*/
2576 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2577 {
2578   PetscFunctionBegin;
2579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2580   PetscValidType(mat, 1);
2581   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2582   VecCheckAssembled(x);
2583   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2584   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2585   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2586   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2587   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);
2588   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);
2589   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);
2590   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);
2591   PetscCall(VecSetErrorIfLocked(y, 3));
2592   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2593   MatCheckPreallocated(mat, 1);
2594 
2595   PetscCall(VecLockReadPush(x));
2596   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2597   PetscUseTypeMethod(mat, mult, x, y);
2598   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2599   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2600   PetscCall(VecLockReadPop(x));
2601   PetscFunctionReturn(PETSC_SUCCESS);
2602 }
2603 
2604 /*@
2605    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2606 
2607    Neighbor-wise Collective
2608 
2609    Input Parameters:
2610 +  mat - the matrix
2611 -  x   - the vector to be multiplied
2612 
2613    Output Parameter:
2614 .  y - the result
2615 
2616    Level: beginner
2617 
2618    Notes:
2619    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2620    call `MatMultTranspose`(A,y,y).
2621 
2622    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2623    use `MatMultHermitianTranspose()`
2624 
2625 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2626 @*/
2627 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2628 {
2629   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2630 
2631   PetscFunctionBegin;
2632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2633   PetscValidType(mat, 1);
2634   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2635   VecCheckAssembled(x);
2636   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2637 
2638   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2639   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2640   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2641   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);
2642   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);
2643   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);
2644   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);
2645   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2646   MatCheckPreallocated(mat, 1);
2647 
2648   if (!mat->ops->multtranspose) {
2649     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2650     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);
2651   } else op = mat->ops->multtranspose;
2652   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2653   PetscCall(VecLockReadPush(x));
2654   PetscCall((*op)(mat, x, y));
2655   PetscCall(VecLockReadPop(x));
2656   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2657   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2658   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2659   PetscFunctionReturn(PETSC_SUCCESS);
2660 }
2661 
2662 /*@
2663    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2664 
2665    Neighbor-wise Collective
2666 
2667    Input Parameters:
2668 +  mat - the matrix
2669 -  x   - the vector to be multilplied
2670 
2671    Output Parameter:
2672 .  y - the result
2673 
2674    Level: beginner
2675 
2676    Notes:
2677    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2678    call `MatMultHermitianTranspose`(A,y,y).
2679 
2680    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2681 
2682    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2683 
2684 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2685 @*/
2686 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2687 {
2688   PetscFunctionBegin;
2689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2690   PetscValidType(mat, 1);
2691   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2692   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2693 
2694   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2695   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2696   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2697   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);
2698   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);
2699   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);
2700   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);
2701   MatCheckPreallocated(mat, 1);
2702 
2703   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2704 #if defined(PETSC_USE_COMPLEX)
2705   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2706     PetscCall(VecLockReadPush(x));
2707     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2708     else PetscUseTypeMethod(mat, mult, x, y);
2709     PetscCall(VecLockReadPop(x));
2710   } else {
2711     Vec w;
2712     PetscCall(VecDuplicate(x, &w));
2713     PetscCall(VecCopy(x, w));
2714     PetscCall(VecConjugate(w));
2715     PetscCall(MatMultTranspose(mat, w, y));
2716     PetscCall(VecDestroy(&w));
2717     PetscCall(VecConjugate(y));
2718   }
2719   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2720 #else
2721   PetscCall(MatMultTranspose(mat, x, y));
2722 #endif
2723   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2724   PetscFunctionReturn(PETSC_SUCCESS);
2725 }
2726 
2727 /*@
2728     MatMultAdd -  Computes v3 = v2 + A * v1.
2729 
2730     Neighbor-wise Collective
2731 
2732     Input Parameters:
2733 +   mat - the matrix
2734 .   v1 - the vector to be multiplied by `mat`
2735 -   v2 - the vector to be added to the result
2736 
2737     Output Parameter:
2738 .   v3 - the result
2739 
2740     Level: beginner
2741 
2742     Note:
2743     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2744     call `MatMultAdd`(A,v1,v2,v1).
2745 
2746 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2747 @*/
2748 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2749 {
2750   PetscFunctionBegin;
2751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2752   PetscValidType(mat, 1);
2753   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2754   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2755   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2756 
2757   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2758   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2759   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);
2760   /* 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);
2761      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); */
2762   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);
2763   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);
2764   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2765   MatCheckPreallocated(mat, 1);
2766 
2767   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2768   PetscCall(VecLockReadPush(v1));
2769   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2770   PetscCall(VecLockReadPop(v1));
2771   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2772   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2773   PetscFunctionReturn(PETSC_SUCCESS);
2774 }
2775 
2776 /*@
2777    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2778 
2779    Neighbor-wise Collective
2780 
2781    Input Parameters:
2782 +  mat - the matrix
2783 .  v1 - the vector to be multiplied by the transpose of the matrix
2784 -  v2 - the vector to be added to the result
2785 
2786    Output Parameter:
2787 .  v3 - the result
2788 
2789    Level: beginner
2790 
2791    Note:
2792    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2793    call `MatMultTransposeAdd`(A,v1,v2,v1).
2794 
2795 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2796 @*/
2797 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2798 {
2799   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2800 
2801   PetscFunctionBegin;
2802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2803   PetscValidType(mat, 1);
2804   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2805   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2806   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2807 
2808   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2809   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2810   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);
2811   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);
2812   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);
2813   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2814   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2815   MatCheckPreallocated(mat, 1);
2816 
2817   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2818   PetscCall(VecLockReadPush(v1));
2819   PetscCall((*op)(mat, v1, v2, v3));
2820   PetscCall(VecLockReadPop(v1));
2821   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2822   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2823   PetscFunctionReturn(PETSC_SUCCESS);
2824 }
2825 
2826 /*@
2827    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2828 
2829    Neighbor-wise Collective
2830 
2831    Input Parameters:
2832 +  mat - the matrix
2833 .  v1 - the vector to be multiplied by the Hermitian transpose
2834 -  v2 - the vector to be added to the result
2835 
2836    Output Parameter:
2837 .  v3 - the result
2838 
2839    Level: beginner
2840 
2841    Note:
2842    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2843    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2844 
2845 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2846 @*/
2847 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2848 {
2849   PetscFunctionBegin;
2850   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2851   PetscValidType(mat, 1);
2852   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2853   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2854   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2855 
2856   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2857   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2858   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2859   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);
2860   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);
2861   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);
2862   MatCheckPreallocated(mat, 1);
2863 
2864   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2865   PetscCall(VecLockReadPush(v1));
2866   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2867   else {
2868     Vec w, z;
2869     PetscCall(VecDuplicate(v1, &w));
2870     PetscCall(VecCopy(v1, w));
2871     PetscCall(VecConjugate(w));
2872     PetscCall(VecDuplicate(v3, &z));
2873     PetscCall(MatMultTranspose(mat, w, z));
2874     PetscCall(VecDestroy(&w));
2875     PetscCall(VecConjugate(z));
2876     if (v2 != v3) {
2877       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2878     } else {
2879       PetscCall(VecAXPY(v3, 1.0, z));
2880     }
2881     PetscCall(VecDestroy(&z));
2882   }
2883   PetscCall(VecLockReadPop(v1));
2884   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2885   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2886   PetscFunctionReturn(PETSC_SUCCESS);
2887 }
2888 
2889 /*@C
2890    MatGetFactorType - gets the type of factorization it is
2891 
2892    Not Collective
2893 
2894    Input Parameter:
2895 .  mat - the matrix
2896 
2897    Output Parameter:
2898 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2899 
2900    Level: intermediate
2901 
2902 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2903           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2904 @*/
2905 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2906 {
2907   PetscFunctionBegin;
2908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2909   PetscValidType(mat, 1);
2910   PetscValidPointer(t, 2);
2911   *t = mat->factortype;
2912   PetscFunctionReturn(PETSC_SUCCESS);
2913 }
2914 
2915 /*@C
2916    MatSetFactorType - sets the type of factorization it is
2917 
2918    Logically Collective
2919 
2920    Input Parameters:
2921 +  mat - the matrix
2922 -  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`
2923 
2924    Level: intermediate
2925 
2926 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2927           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2928 @*/
2929 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2930 {
2931   PetscFunctionBegin;
2932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2933   PetscValidType(mat, 1);
2934   mat->factortype = t;
2935   PetscFunctionReturn(PETSC_SUCCESS);
2936 }
2937 
2938 /*@C
2939    MatGetInfo - Returns information about matrix storage (number of
2940    nonzeros, memory, etc.).
2941 
2942    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2943 
2944    Input Parameters:
2945 +  mat - the matrix
2946 -  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)
2947 
2948    Output Parameter:
2949 .  info - matrix information context
2950 
2951    Options Database Key:
2952 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2953 
2954    Notes:
2955    The `MatInfo` context contains a variety of matrix data, including
2956    number of nonzeros allocated and used, number of mallocs during
2957    matrix assembly, etc.  Additional information for factored matrices
2958    is provided (such as the fill ratio, number of mallocs during
2959    factorization, etc.).
2960 
2961    Example:
2962    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2963    data within the MatInfo context.  For example,
2964 .vb
2965       MatInfo info;
2966       Mat     A;
2967       double  mal, nz_a, nz_u;
2968 
2969       MatGetInfo(A, MAT_LOCAL, &info);
2970       mal  = info.mallocs;
2971       nz_a = info.nz_allocated;
2972 .ve
2973 
2974    Fortran users should declare info as a double precision
2975    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2976    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2977    a complete list of parameter names.
2978 .vb
2979       double  precision info(MAT_INFO_SIZE)
2980       double  precision mal, nz_a
2981       Mat     A
2982       integer ierr
2983 
2984       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2985       mal = info(MAT_INFO_MALLOCS)
2986       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2987 .ve
2988 
2989     Level: intermediate
2990 
2991     Developer Note:
2992     The Fortran interface is not autogenerated as the
2993     interface definition cannot be generated correctly [due to `MatInfo` argument]
2994 
2995 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2996 @*/
2997 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2998 {
2999   PetscFunctionBegin;
3000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3001   PetscValidType(mat, 1);
3002   PetscValidPointer(info, 3);
3003   MatCheckPreallocated(mat, 1);
3004   PetscUseTypeMethod(mat, getinfo, flag, info);
3005   PetscFunctionReturn(PETSC_SUCCESS);
3006 }
3007 
3008 /*
3009    This is used by external packages where it is not easy to get the info from the actual
3010    matrix factorization.
3011 */
3012 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3013 {
3014   PetscFunctionBegin;
3015   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3016   PetscFunctionReturn(PETSC_SUCCESS);
3017 }
3018 
3019 /*@C
3020    MatLUFactor - Performs in-place LU factorization of matrix.
3021 
3022    Collective
3023 
3024    Input Parameters:
3025 +  mat - the matrix
3026 .  row - row permutation
3027 .  col - column permutation
3028 -  info - options for factorization, includes
3029 .vb
3030           fill - expected fill as ratio of original fill.
3031           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3032                    Run with the option -info to determine an optimal value to use
3033 .ve
3034    Level: developer
3035 
3036    Notes:
3037    Most users should employ the `KSP` interface for linear solvers
3038    instead of working directly with matrix algebra routines such as this.
3039    See, e.g., `KSPCreate()`.
3040 
3041    This changes the state of the matrix to a factored matrix; it cannot be used
3042    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3043 
3044    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3045    when not using `KSP`.
3046 
3047    Developer Note:
3048    The Fortran interface is not autogenerated as the
3049    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3050 
3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3052           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3053 @*/
3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3055 {
3056   MatFactorInfo tinfo;
3057 
3058   PetscFunctionBegin;
3059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3062   if (info) PetscValidPointer(info, 4);
3063   PetscValidType(mat, 1);
3064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3065   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3066   MatCheckPreallocated(mat, 1);
3067   if (!info) {
3068     PetscCall(MatFactorInfoInitialize(&tinfo));
3069     info = &tinfo;
3070   }
3071 
3072   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3073   PetscUseTypeMethod(mat, lufactor, row, col, info);
3074   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3075   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3076   PetscFunctionReturn(PETSC_SUCCESS);
3077 }
3078 
3079 /*@C
3080    MatILUFactor - Performs in-place ILU factorization of matrix.
3081 
3082    Collective
3083 
3084    Input Parameters:
3085 +  mat - the matrix
3086 .  row - row permutation
3087 .  col - column permutation
3088 -  info - structure containing
3089 .vb
3090       levels - number of levels of fill.
3091       expected fill - as ratio of original fill.
3092       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3093                 missing diagonal entries)
3094 .ve
3095 
3096    Level: developer
3097 
3098    Notes:
3099    Most users should employ the `KSP` interface for linear solvers
3100    instead of working directly with matrix algebra routines such as this.
3101    See, e.g., `KSPCreate()`.
3102 
3103    Probably really in-place only when level of fill is zero, otherwise allocates
3104    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3105    when not using `KSP`.
3106 
3107    Developer Note:
3108    The Fortran interface is not autogenerated as the
3109    interface definition cannot be generated correctly [due to MatFactorInfo]
3110 
3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3112 @*/
3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3114 {
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3117   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3118   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3119   PetscValidPointer(info, 4);
3120   PetscValidType(mat, 1);
3121   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3123   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3124   MatCheckPreallocated(mat, 1);
3125 
3126   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3127   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3128   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3129   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3130   PetscFunctionReturn(PETSC_SUCCESS);
3131 }
3132 
3133 /*@C
3134    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3135    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3136 
3137    Collective
3138 
3139    Input Parameters:
3140 +  fact - the factor matrix obtained with `MatGetFactor()`
3141 .  mat - the matrix
3142 .  row - the row permutation
3143 .  col - the column permutation
3144 -  info - options for factorization, includes
3145 .vb
3146           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3147           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3148 .ve
3149 
3150    Level: developer
3151 
3152    Notes:
3153     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3154 
3155    Most users should employ the simplified `KSP` interface for linear solvers
3156    instead of working directly with matrix algebra routines such as this.
3157    See, e.g., `KSPCreate()`.
3158 
3159    Developer Note:
3160    The Fortran interface is not autogenerated as the
3161    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3162 
3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3164 @*/
3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3166 {
3167   MatFactorInfo tinfo;
3168 
3169   PetscFunctionBegin;
3170   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3172   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3173   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3174   if (info) PetscValidPointer(info, 5);
3175   PetscValidType(fact, 1);
3176   PetscValidType(mat, 2);
3177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3179   MatCheckPreallocated(mat, 2);
3180   if (!info) {
3181     PetscCall(MatFactorInfoInitialize(&tinfo));
3182     info = &tinfo;
3183   }
3184 
3185   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3186   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3189   PetscFunctionReturn(PETSC_SUCCESS);
3190 }
3191 
3192 /*@C
3193    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3194    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3195 
3196    Collective
3197 
3198    Input Parameters:
3199 +  fact - the factor matrix obtained with `MatGetFactor()`
3200 .  mat - the matrix
3201 -  info - options for factorization
3202 
3203    Level: developer
3204 
3205    Notes:
3206    See `MatLUFactor()` for in-place factorization.  See
3207    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3208 
3209    Most users should employ the `KSP` interface for linear solvers
3210    instead of working directly with matrix algebra routines such as this.
3211    See, e.g., `KSPCreate()`.
3212 
3213     Developer Note:
3214     The Fortran interface is not autogenerated as the
3215     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3216 
3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3218 @*/
3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3220 {
3221   MatFactorInfo tinfo;
3222 
3223   PetscFunctionBegin;
3224   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3226   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3227   PetscValidType(fact, 1);
3228   PetscValidType(mat, 2);
3229   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3230   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,
3231              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3232 
3233   MatCheckPreallocated(mat, 2);
3234   if (!info) {
3235     PetscCall(MatFactorInfoInitialize(&tinfo));
3236     info = &tinfo;
3237   }
3238 
3239   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3240   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3241   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3242   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3243   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3244   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3245   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3246   PetscFunctionReturn(PETSC_SUCCESS);
3247 }
3248 
3249 /*@C
3250    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3251    symmetric matrix.
3252 
3253    Collective
3254 
3255    Input Parameters:
3256 +  mat - the matrix
3257 .  perm - row and column permutations
3258 -  f - expected fill as ratio of original fill
3259 
3260    Level: developer
3261 
3262    Notes:
3263    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3264    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3265 
3266    Most users should employ the `KSP` interface for linear solvers
3267    instead of working directly with matrix algebra routines such as this.
3268    See, e.g., `KSPCreate()`.
3269 
3270    Developer Note:
3271    The Fortran interface is not autogenerated as the
3272    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3273 
3274 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3275           `MatGetOrdering()`
3276 @*/
3277 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3278 {
3279   MatFactorInfo tinfo;
3280 
3281   PetscFunctionBegin;
3282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3283   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3284   if (info) PetscValidPointer(info, 3);
3285   PetscValidType(mat, 1);
3286   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3287   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3288   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3289   MatCheckPreallocated(mat, 1);
3290   if (!info) {
3291     PetscCall(MatFactorInfoInitialize(&tinfo));
3292     info = &tinfo;
3293   }
3294 
3295   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3296   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3297   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3298   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3299   PetscFunctionReturn(PETSC_SUCCESS);
3300 }
3301 
3302 /*@C
3303    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3304    of a symmetric matrix.
3305 
3306    Collective
3307 
3308    Input Parameters:
3309 +  fact - the factor matrix obtained with `MatGetFactor()`
3310 .  mat - the matrix
3311 .  perm - row and column permutations
3312 -  info - options for factorization, includes
3313 .vb
3314           fill - expected fill as ratio of original fill.
3315           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3316                    Run with the option -info to determine an optimal value to use
3317 .ve
3318 
3319    Level: developer
3320 
3321    Notes:
3322    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3323    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3324 
3325    Most users should employ the `KSP` interface for linear solvers
3326    instead of working directly with matrix algebra routines such as this.
3327    See, e.g., `KSPCreate()`.
3328 
3329    Developer Note:
3330    The Fortran interface is not autogenerated as the
3331    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3332 
3333 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3334           `MatGetOrdering()`
3335 @*/
3336 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3337 {
3338   MatFactorInfo tinfo;
3339 
3340   PetscFunctionBegin;
3341   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3343   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3344   if (info) PetscValidPointer(info, 4);
3345   PetscValidType(fact, 1);
3346   PetscValidType(mat, 2);
3347   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3348   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3349   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3350   MatCheckPreallocated(mat, 2);
3351   if (!info) {
3352     PetscCall(MatFactorInfoInitialize(&tinfo));
3353     info = &tinfo;
3354   }
3355 
3356   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3357   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3358   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3359   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3360   PetscFunctionReturn(PETSC_SUCCESS);
3361 }
3362 
3363 /*@C
3364    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3365    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3366    `MatCholeskyFactorSymbolic()`.
3367 
3368    Collective
3369 
3370    Input Parameters:
3371 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3372 .  mat - the initial matrix that is to be factored
3373 -  info - options for factorization
3374 
3375    Level: developer
3376 
3377    Note:
3378    Most users should employ the `KSP` interface for linear solvers
3379    instead of working directly with matrix algebra routines such as this.
3380    See, e.g., `KSPCreate()`.
3381 
3382    Developer Note:
3383    The Fortran interface is not autogenerated as the
3384    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3385 
3386 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3387 @*/
3388 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3389 {
3390   MatFactorInfo tinfo;
3391 
3392   PetscFunctionBegin;
3393   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3395   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3396   PetscValidType(fact, 1);
3397   PetscValidType(mat, 2);
3398   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3399   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,
3400              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3401   MatCheckPreallocated(mat, 2);
3402   if (!info) {
3403     PetscCall(MatFactorInfoInitialize(&tinfo));
3404     info = &tinfo;
3405   }
3406 
3407   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3408   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3409   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3410   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3411   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3412   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3413   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3414   PetscFunctionReturn(PETSC_SUCCESS);
3415 }
3416 
3417 /*@
3418    MatQRFactor - Performs in-place QR factorization of matrix.
3419 
3420    Collective
3421 
3422    Input Parameters:
3423 +  mat - the matrix
3424 .  col - column permutation
3425 -  info - options for factorization, includes
3426 .vb
3427           fill - expected fill as ratio of original fill.
3428           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3429                    Run with the option -info to determine an optimal value to use
3430 .ve
3431 
3432    Level: developer
3433 
3434    Notes:
3435    Most users should employ the `KSP` interface for linear solvers
3436    instead of working directly with matrix algebra routines such as this.
3437    See, e.g., `KSPCreate()`.
3438 
3439    This changes the state of the matrix to a factored matrix; it cannot be used
3440    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3441 
3442    Developer Note:
3443    The Fortran interface is not autogenerated as the
3444    interface definition cannot be generated correctly [due to MatFactorInfo]
3445 
3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3447           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3448 @*/
3449 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3450 {
3451   PetscFunctionBegin;
3452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3453   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3454   if (info) PetscValidPointer(info, 3);
3455   PetscValidType(mat, 1);
3456   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3457   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3458   MatCheckPreallocated(mat, 1);
3459   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3460   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3461   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3462   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3463   PetscFunctionReturn(PETSC_SUCCESS);
3464 }
3465 
3466 /*@
3467    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3468    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3469 
3470    Collective
3471 
3472    Input Parameters:
3473 +  fact - the factor matrix obtained with `MatGetFactor()`
3474 .  mat - the matrix
3475 .  col - column permutation
3476 -  info - options for factorization, includes
3477 .vb
3478           fill - expected fill as ratio of original fill.
3479           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3480                    Run with the option -info to determine an optimal value to use
3481 .ve
3482 
3483    Level: developer
3484 
3485    Note:
3486    Most users should employ the `KSP` interface for linear solvers
3487    instead of working directly with matrix algebra routines such as this.
3488    See, e.g., `KSPCreate()`.
3489 
3490    Developer Note:
3491    The Fortran interface is not autogenerated as the
3492    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3493 
3494 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3495 @*/
3496 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3497 {
3498   MatFactorInfo tinfo;
3499 
3500   PetscFunctionBegin;
3501   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3503   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3504   if (info) PetscValidPointer(info, 4);
3505   PetscValidType(fact, 1);
3506   PetscValidType(mat, 2);
3507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3509   MatCheckPreallocated(mat, 2);
3510   if (!info) {
3511     PetscCall(MatFactorInfoInitialize(&tinfo));
3512     info = &tinfo;
3513   }
3514 
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3517   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3518   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3519   PetscFunctionReturn(PETSC_SUCCESS);
3520 }
3521 
3522 /*@
3523    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3524    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3525 
3526    Collective
3527 
3528    Input Parameters:
3529 +  fact - the factor matrix obtained with `MatGetFactor()`
3530 .  mat - the matrix
3531 -  info - options for factorization
3532 
3533    Level: developer
3534 
3535    Notes:
3536    See `MatQRFactor()` for in-place factorization.
3537 
3538    Most users should employ the `KSP` interface for linear solvers
3539    instead of working directly with matrix algebra routines such as this.
3540    See, e.g., `KSPCreate()`.
3541 
3542    Developer Note:
3543    The Fortran interface is not autogenerated as the
3544    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3545 
3546 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3547 @*/
3548 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3549 {
3550   MatFactorInfo tinfo;
3551 
3552   PetscFunctionBegin;
3553   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3555   PetscValidType(fact, 1);
3556   PetscValidType(mat, 2);
3557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3558   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,
3559              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3560 
3561   MatCheckPreallocated(mat, 2);
3562   if (!info) {
3563     PetscCall(MatFactorInfoInitialize(&tinfo));
3564     info = &tinfo;
3565   }
3566 
3567   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3568   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3569   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3570   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3571   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3572   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3573   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3574   PetscFunctionReturn(PETSC_SUCCESS);
3575 }
3576 
3577 /*@
3578    MatSolve - Solves A x = b, given a factored matrix.
3579 
3580    Neighbor-wise Collective
3581 
3582    Input Parameters:
3583 +  mat - the factored matrix
3584 -  b - the right-hand-side vector
3585 
3586    Output Parameter:
3587 .  x - the result vector
3588 
3589    Level: developer
3590 
3591    Notes:
3592    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3593    call `MatSolve`(A,x,x).
3594 
3595    Most users should employ the `KSP` interface for linear solvers
3596    instead of working directly with matrix algebra routines such as this.
3597    See, e.g., `KSPCreate()`.
3598 
3599 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3600 @*/
3601 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3602 {
3603   PetscFunctionBegin;
3604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3605   PetscValidType(mat, 1);
3606   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3607   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3608   PetscCheckSameComm(mat, 1, b, 2);
3609   PetscCheckSameComm(mat, 1, x, 3);
3610   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3611   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);
3612   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);
3613   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);
3614   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3615   MatCheckPreallocated(mat, 1);
3616 
3617   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3618   if (mat->factorerrortype) {
3619     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3620     PetscCall(VecSetInf(x));
3621   } else PetscUseTypeMethod(mat, solve, b, x);
3622   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3623   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3624   PetscFunctionReturn(PETSC_SUCCESS);
3625 }
3626 
3627 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3628 {
3629   Vec      b, x;
3630   PetscInt N, i;
3631   PetscErrorCode (*f)(Mat, Vec, Vec);
3632   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3633 
3634   PetscFunctionBegin;
3635   if (A->factorerrortype) {
3636     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3637     PetscCall(MatSetInf(X));
3638     PetscFunctionReturn(PETSC_SUCCESS);
3639   }
3640   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3641   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3642   PetscCall(MatBoundToCPU(A, &Abound));
3643   if (!Abound) {
3644     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3645     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3646   }
3647 #if PetscDefined(HAVE_CUDA)
3648   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3649   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3650 #elif PetscDefined(HAVE_HIP)
3651   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3652   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3653 #endif
3654   PetscCall(MatGetSize(B, NULL, &N));
3655   for (i = 0; i < N; i++) {
3656     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3657     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3658     PetscCall((*f)(A, b, x));
3659     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3660     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3661   }
3662   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3663   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3664   PetscFunctionReturn(PETSC_SUCCESS);
3665 }
3666 
3667 /*@
3668    MatMatSolve - Solves A X = B, given a factored matrix.
3669 
3670    Neighbor-wise Collective
3671 
3672    Input Parameters:
3673 +  A - the factored matrix
3674 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3675 
3676    Output Parameter:
3677 .  X - the result matrix (dense matrix)
3678 
3679    Level: developer
3680 
3681    Note:
3682    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3683    otherwise, `B` and `X` cannot be the same.
3684 
3685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3686 @*/
3687 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3688 {
3689   PetscFunctionBegin;
3690   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3691   PetscValidType(A, 1);
3692   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3693   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3694   PetscCheckSameComm(A, 1, B, 2);
3695   PetscCheckSameComm(A, 1, X, 3);
3696   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);
3697   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);
3698   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");
3699   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3700   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3701   MatCheckPreallocated(A, 1);
3702 
3703   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3704   if (!A->ops->matsolve) {
3705     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3706     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3707   } else PetscUseTypeMethod(A, matsolve, B, X);
3708   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3709   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3710   PetscFunctionReturn(PETSC_SUCCESS);
3711 }
3712 
3713 /*@
3714    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3715 
3716    Neighbor-wise Collective
3717 
3718    Input Parameters:
3719 +  A - the factored matrix
3720 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3721 
3722    Output Parameter:
3723 .  X - the result matrix (dense matrix)
3724 
3725    Level: developer
3726 
3727    Note:
3728    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3729    call `MatMatSolveTranspose`(A,X,X).
3730 
3731 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3732 @*/
3733 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3734 {
3735   PetscFunctionBegin;
3736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3737   PetscValidType(A, 1);
3738   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3739   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3740   PetscCheckSameComm(A, 1, B, 2);
3741   PetscCheckSameComm(A, 1, X, 3);
3742   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3743   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);
3744   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);
3745   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);
3746   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");
3747   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3748   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3749   MatCheckPreallocated(A, 1);
3750 
3751   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3752   if (!A->ops->matsolvetranspose) {
3753     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3754     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3755   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3756   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3757   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3758   PetscFunctionReturn(PETSC_SUCCESS);
3759 }
3760 
3761 /*@
3762    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3763 
3764    Neighbor-wise Collective
3765 
3766    Input Parameters:
3767 +  A - the factored matrix
3768 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3769 
3770    Output Parameter:
3771 .  X - the result matrix (dense matrix)
3772 
3773    Level: developer
3774 
3775    Note:
3776    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
3777    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3778 
3779 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3780 @*/
3781 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3782 {
3783   PetscFunctionBegin;
3784   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3785   PetscValidType(A, 1);
3786   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3787   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3788   PetscCheckSameComm(A, 1, Bt, 2);
3789   PetscCheckSameComm(A, 1, X, 3);
3790 
3791   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3792   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);
3793   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);
3794   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");
3795   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3796   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3797   MatCheckPreallocated(A, 1);
3798 
3799   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3800   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3801   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3802   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3803   PetscFunctionReturn(PETSC_SUCCESS);
3804 }
3805 
3806 /*@
3807    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3808                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3809 
3810    Neighbor-wise Collective
3811 
3812    Input Parameters:
3813 +  mat - the factored matrix
3814 -  b - the right-hand-side vector
3815 
3816    Output Parameter:
3817 .  x - the result vector
3818 
3819    Level: developer
3820 
3821    Notes:
3822    `MatSolve()` should be used for most applications, as it performs
3823    a forward solve followed by a backward solve.
3824 
3825    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3826    call `MatForwardSolve`(A,x,x).
3827 
3828    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3829    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3830    `MatForwardSolve()` solves U^T*D y = b, and
3831    `MatBackwardSolve()` solves U x = y.
3832    Thus they do not provide a symmetric preconditioner.
3833 
3834 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3835 @*/
3836 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3837 {
3838   PetscFunctionBegin;
3839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3840   PetscValidType(mat, 1);
3841   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3842   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3843   PetscCheckSameComm(mat, 1, b, 2);
3844   PetscCheckSameComm(mat, 1, x, 3);
3845   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3846   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);
3847   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);
3848   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);
3849   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3850   MatCheckPreallocated(mat, 1);
3851 
3852   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3853   PetscUseTypeMethod(mat, forwardsolve, b, x);
3854   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3855   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3856   PetscFunctionReturn(PETSC_SUCCESS);
3857 }
3858 
3859 /*@
3860    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3861                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3862 
3863    Neighbor-wise Collective
3864 
3865    Input Parameters:
3866 +  mat - the factored matrix
3867 -  b - the right-hand-side vector
3868 
3869    Output Parameter:
3870 .  x - the result vector
3871 
3872    Level: developer
3873 
3874    Notes:
3875    `MatSolve()` should be used for most applications, as it performs
3876    a forward solve followed by a backward solve.
3877 
3878    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3879    call `MatBackwardSolve`(A,x,x).
3880 
3881    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3882    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3883    `MatForwardSolve()` solves U^T*D y = b, and
3884    `MatBackwardSolve()` solves U x = y.
3885    Thus they do not provide a symmetric preconditioner.
3886 
3887 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3888 @*/
3889 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3890 {
3891   PetscFunctionBegin;
3892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3893   PetscValidType(mat, 1);
3894   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3895   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3896   PetscCheckSameComm(mat, 1, b, 2);
3897   PetscCheckSameComm(mat, 1, x, 3);
3898   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3899   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);
3900   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);
3901   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);
3902   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3903   MatCheckPreallocated(mat, 1);
3904 
3905   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3906   PetscUseTypeMethod(mat, backwardsolve, b, x);
3907   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3908   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3909   PetscFunctionReturn(PETSC_SUCCESS);
3910 }
3911 
3912 /*@
3913    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3914 
3915    Neighbor-wise Collective
3916 
3917    Input Parameters:
3918 +  mat - the factored matrix
3919 .  b - the right-hand-side vector
3920 -  y - the vector to be added to
3921 
3922    Output Parameter:
3923 .  x - the result vector
3924 
3925    Level: developer
3926 
3927    Note:
3928    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3929    call `MatSolveAdd`(A,x,y,x).
3930 
3931 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3932 @*/
3933 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3934 {
3935   PetscScalar one = 1.0;
3936   Vec         tmp;
3937 
3938   PetscFunctionBegin;
3939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3940   PetscValidType(mat, 1);
3941   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3942   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3943   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3944   PetscCheckSameComm(mat, 1, b, 2);
3945   PetscCheckSameComm(mat, 1, y, 3);
3946   PetscCheckSameComm(mat, 1, x, 4);
3947   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3948   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);
3949   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);
3950   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);
3951   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);
3952   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);
3953   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3954   MatCheckPreallocated(mat, 1);
3955 
3956   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3957   if (mat->factorerrortype) {
3958     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3959     PetscCall(VecSetInf(x));
3960   } else if (mat->ops->solveadd) {
3961     PetscUseTypeMethod(mat, solveadd, b, y, x);
3962   } else {
3963     /* do the solve then the add manually */
3964     if (x != y) {
3965       PetscCall(MatSolve(mat, b, x));
3966       PetscCall(VecAXPY(x, one, y));
3967     } else {
3968       PetscCall(VecDuplicate(x, &tmp));
3969       PetscCall(VecCopy(x, tmp));
3970       PetscCall(MatSolve(mat, b, x));
3971       PetscCall(VecAXPY(x, one, tmp));
3972       PetscCall(VecDestroy(&tmp));
3973     }
3974   }
3975   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3976   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3977   PetscFunctionReturn(PETSC_SUCCESS);
3978 }
3979 
3980 /*@
3981    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3982 
3983    Neighbor-wise Collective
3984 
3985    Input Parameters:
3986 +  mat - the factored matrix
3987 -  b - the right-hand-side vector
3988 
3989    Output Parameter:
3990 .  x - the result vector
3991 
3992    Level: developer
3993 
3994    Notes:
3995    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3996    call `MatSolveTranspose`(A,x,x).
3997 
3998    Most users should employ the `KSP` interface for linear solvers
3999    instead of working directly with matrix algebra routines such as this.
4000    See, e.g., `KSPCreate()`.
4001 
4002 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4003 @*/
4004 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4005 {
4006   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4007 
4008   PetscFunctionBegin;
4009   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4010   PetscValidType(mat, 1);
4011   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4012   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4013   PetscCheckSameComm(mat, 1, b, 2);
4014   PetscCheckSameComm(mat, 1, x, 3);
4015   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4016   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);
4017   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);
4018   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4019   MatCheckPreallocated(mat, 1);
4020   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4021   if (mat->factorerrortype) {
4022     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4023     PetscCall(VecSetInf(x));
4024   } else {
4025     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4026     PetscCall((*f)(mat, b, x));
4027   }
4028   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4029   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4030   PetscFunctionReturn(PETSC_SUCCESS);
4031 }
4032 
4033 /*@
4034    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4035                       factored matrix.
4036 
4037    Neighbor-wise Collective
4038 
4039    Input Parameters:
4040 +  mat - the factored matrix
4041 .  b - the right-hand-side vector
4042 -  y - the vector to be added to
4043 
4044    Output Parameter:
4045 .  x - the result vector
4046 
4047    Level: developer
4048 
4049    Note:
4050    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4051    call `MatSolveTransposeAdd`(A,x,y,x).
4052 
4053 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4054 @*/
4055 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4056 {
4057   PetscScalar one = 1.0;
4058   Vec         tmp;
4059   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4060 
4061   PetscFunctionBegin;
4062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4063   PetscValidType(mat, 1);
4064   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4065   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4066   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4067   PetscCheckSameComm(mat, 1, b, 2);
4068   PetscCheckSameComm(mat, 1, y, 3);
4069   PetscCheckSameComm(mat, 1, x, 4);
4070   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4071   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);
4072   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);
4073   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);
4074   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);
4075   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4076   MatCheckPreallocated(mat, 1);
4077 
4078   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4079   if (mat->factorerrortype) {
4080     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4081     PetscCall(VecSetInf(x));
4082   } else if (f) {
4083     PetscCall((*f)(mat, b, y, x));
4084   } else {
4085     /* do the solve then the add manually */
4086     if (x != y) {
4087       PetscCall(MatSolveTranspose(mat, b, x));
4088       PetscCall(VecAXPY(x, one, y));
4089     } else {
4090       PetscCall(VecDuplicate(x, &tmp));
4091       PetscCall(VecCopy(x, tmp));
4092       PetscCall(MatSolveTranspose(mat, b, x));
4093       PetscCall(VecAXPY(x, one, tmp));
4094       PetscCall(VecDestroy(&tmp));
4095     }
4096   }
4097   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4098   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4099   PetscFunctionReturn(PETSC_SUCCESS);
4100 }
4101 
4102 /*@
4103    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4104 
4105    Neighbor-wise Collective
4106 
4107    Input Parameters:
4108 +  mat - the matrix
4109 .  b - the right hand side
4110 .  omega - the relaxation factor
4111 .  flag - flag indicating the type of SOR (see below)
4112 .  shift -  diagonal shift
4113 .  its - the number of iterations
4114 -  lits - the number of local iterations
4115 
4116    Output Parameter:
4117 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4118 
4119    SOR Flags:
4120 +     `SOR_FORWARD_SWEEP` - forward SOR
4121 .     `SOR_BACKWARD_SWEEP` - backward SOR
4122 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4123 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4124 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4125 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4126 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4127 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4128          upper/lower triangular part of matrix to
4129          vector (with omega)
4130 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4131 
4132    Level: developer
4133 
4134    Notes:
4135    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4136    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4137    on each processor.
4138 
4139    Application programmers will not generally use `MatSOR()` directly,
4140    but instead will employ the `KSP`/`PC` interface.
4141 
4142    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4143 
4144    Most users should employ the `KSP` interface for linear solvers
4145    instead of working directly with matrix algebra routines such as this.
4146    See, e.g., `KSPCreate()`.
4147 
4148    Vectors `x` and `b` CANNOT be the same
4149 
4150    The flags are implemented as bitwise inclusive or operations.
4151    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4152    to specify a zero initial guess for SSOR.
4153 
4154    Developer Note:
4155    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4156 
4157 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4158 @*/
4159 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4160 {
4161   PetscFunctionBegin;
4162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4163   PetscValidType(mat, 1);
4164   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4165   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4166   PetscCheckSameComm(mat, 1, b, 2);
4167   PetscCheckSameComm(mat, 1, x, 8);
4168   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4169   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4170   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);
4171   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);
4172   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);
4173   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4174   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4175   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4176 
4177   MatCheckPreallocated(mat, 1);
4178   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4179   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4180   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4181   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4182   PetscFunctionReturn(PETSC_SUCCESS);
4183 }
4184 
4185 /*
4186       Default matrix copy routine.
4187 */
4188 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4189 {
4190   PetscInt           i, rstart = 0, rend = 0, nz;
4191   const PetscInt    *cwork;
4192   const PetscScalar *vwork;
4193 
4194   PetscFunctionBegin;
4195   if (B->assembled) PetscCall(MatZeroEntries(B));
4196   if (str == SAME_NONZERO_PATTERN) {
4197     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4198     for (i = rstart; i < rend; i++) {
4199       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4200       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4201       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4202     }
4203   } else {
4204     PetscCall(MatAYPX(B, 0.0, A, str));
4205   }
4206   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4207   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4208   PetscFunctionReturn(PETSC_SUCCESS);
4209 }
4210 
4211 /*@
4212    MatCopy - Copies a matrix to another matrix.
4213 
4214    Collective
4215 
4216    Input Parameters:
4217 +  A - the matrix
4218 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4219 
4220    Output Parameter:
4221 .  B - where the copy is put
4222 
4223    Level: intermediate
4224 
4225    Notes:
4226    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4227 
4228    `MatCopy()` copies the matrix entries of a matrix to another existing
4229    matrix (after first zeroing the second matrix).  A related routine is
4230    `MatConvert()`, which first creates a new matrix and then copies the data.
4231 
4232 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4233 @*/
4234 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4235 {
4236   PetscInt i;
4237 
4238   PetscFunctionBegin;
4239   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4240   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4241   PetscValidType(A, 1);
4242   PetscValidType(B, 2);
4243   PetscCheckSameComm(A, 1, B, 2);
4244   MatCheckPreallocated(B, 2);
4245   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4246   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4247   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,
4248              A->cmap->N, B->cmap->N);
4249   MatCheckPreallocated(A, 1);
4250   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4251 
4252   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4253   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4254   else PetscCall(MatCopy_Basic(A, B, str));
4255 
4256   B->stencil.dim = A->stencil.dim;
4257   B->stencil.noc = A->stencil.noc;
4258   for (i = 0; i <= A->stencil.dim; i++) {
4259     B->stencil.dims[i]   = A->stencil.dims[i];
4260     B->stencil.starts[i] = A->stencil.starts[i];
4261   }
4262 
4263   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4264   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4265   PetscFunctionReturn(PETSC_SUCCESS);
4266 }
4267 
4268 /*@C
4269    MatConvert - Converts a matrix to another matrix, either of the same
4270    or different type.
4271 
4272    Collective
4273 
4274    Input Parameters:
4275 +  mat - the matrix
4276 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4277    same type as the original matrix.
4278 -  reuse - denotes if the destination matrix is to be created or reused.
4279    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
4280    `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).
4281 
4282    Output Parameter:
4283 .  M - pointer to place new matrix
4284 
4285    Level: intermediate
4286 
4287    Notes:
4288    `MatConvert()` first creates a new matrix and then copies the data from
4289    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4290    entries of one matrix to another already existing matrix context.
4291 
4292    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4293    the MPI communicator of the generated matrix is always the same as the communicator
4294    of the input matrix.
4295 
4296 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4297 @*/
4298 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4299 {
4300   PetscBool  sametype, issame, flg;
4301   PetscBool3 issymmetric, ishermitian;
4302   char       convname[256], mtype[256];
4303   Mat        B;
4304 
4305   PetscFunctionBegin;
4306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4307   PetscValidType(mat, 1);
4308   PetscValidPointer(M, 4);
4309   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4310   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4311   MatCheckPreallocated(mat, 1);
4312 
4313   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4314   if (flg) newtype = mtype;
4315 
4316   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4317   PetscCall(PetscStrcmp(newtype, "same", &issame));
4318   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4319   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");
4320 
4321   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4322     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4323     PetscFunctionReturn(PETSC_SUCCESS);
4324   }
4325 
4326   /* Cache Mat options because some converters use MatHeaderReplace  */
4327   issymmetric = mat->symmetric;
4328   ishermitian = mat->hermitian;
4329 
4330   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4331     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4332     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4333   } else {
4334     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4335     const char *prefix[3]                                 = {"seq", "mpi", ""};
4336     PetscInt    i;
4337     /*
4338        Order of precedence:
4339        0) See if newtype is a superclass of the current matrix.
4340        1) See if a specialized converter is known to the current matrix.
4341        2) See if a specialized converter is known to the desired matrix class.
4342        3) See if a good general converter is registered for the desired class
4343           (as of 6/27/03 only MATMPIADJ falls into this category).
4344        4) See if a good general converter is known for the current matrix.
4345        5) Use a really basic converter.
4346     */
4347 
4348     /* 0) See if newtype is a superclass of the current matrix.
4349           i.e mat is mpiaij and newtype is aij */
4350     for (i = 0; i < 2; i++) {
4351       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4353       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4354       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4355       if (flg) {
4356         if (reuse == MAT_INPLACE_MATRIX) {
4357           PetscCall(PetscInfo(mat, "Early return\n"));
4358           PetscFunctionReturn(PETSC_SUCCESS);
4359         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4360           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4361           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4364           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4365           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         }
4368       }
4369     }
4370     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4371     for (i = 0; i < 3; i++) {
4372       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4378       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4379       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4380       if (conv) goto foundconv;
4381     }
4382 
4383     /* 2)  See if a specialized converter is known to the desired matrix class. */
4384     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4385     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4386     PetscCall(MatSetType(B, newtype));
4387     for (i = 0; i < 3; i++) {
4388       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4394       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4395       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4396       if (conv) {
4397         PetscCall(MatDestroy(&B));
4398         goto foundconv;
4399       }
4400     }
4401 
4402     /* 3) See if a good general converter is registered for the desired class */
4403     conv = B->ops->convertfrom;
4404     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4405     PetscCall(MatDestroy(&B));
4406     if (conv) goto foundconv;
4407 
4408     /* 4) See if a good general converter is known for the current matrix */
4409     if (mat->ops->convert) conv = mat->ops->convert;
4410     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4411     if (conv) goto foundconv;
4412 
4413     /* 5) Use a really basic converter. */
4414     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4415     conv = MatConvert_Basic;
4416 
4417   foundconv:
4418     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4419     PetscCall((*conv)(mat, newtype, reuse, M));
4420     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4421       /* the block sizes must be same if the mappings are copied over */
4422       (*M)->rmap->bs = mat->rmap->bs;
4423       (*M)->cmap->bs = mat->cmap->bs;
4424       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4425       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4426       (*M)->rmap->mapping = mat->rmap->mapping;
4427       (*M)->cmap->mapping = mat->cmap->mapping;
4428     }
4429     (*M)->stencil.dim = mat->stencil.dim;
4430     (*M)->stencil.noc = mat->stencil.noc;
4431     for (i = 0; i <= mat->stencil.dim; i++) {
4432       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4433       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4434     }
4435     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4436   }
4437   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4438 
4439   /* Copy Mat options */
4440   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4441   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4442   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4443   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4444   PetscFunctionReturn(PETSC_SUCCESS);
4445 }
4446 
4447 /*@C
4448    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4449 
4450    Not Collective
4451 
4452    Input Parameter:
4453 .  mat - the matrix, must be a factored matrix
4454 
4455    Output Parameter:
4456 .   type - the string name of the package (do not free this string)
4457 
4458    Level: intermediate
4459 
4460    Fortran Note:
4461    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4462 
4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4464 @*/
4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4466 {
4467   PetscErrorCode (*conv)(Mat, MatSolverType *);
4468 
4469   PetscFunctionBegin;
4470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4471   PetscValidType(mat, 1);
4472   PetscValidPointer(type, 2);
4473   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4474   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4475   if (conv) PetscCall((*conv)(mat, type));
4476   else *type = MATSOLVERPETSC;
4477   PetscFunctionReturn(PETSC_SUCCESS);
4478 }
4479 
4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4481 struct _MatSolverTypeForSpecifcType {
4482   MatType mtype;
4483   /* no entry for MAT_FACTOR_NONE */
4484   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4485   MatSolverTypeForSpecifcType next;
4486 };
4487 
4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4489 struct _MatSolverTypeHolder {
4490   char                       *name;
4491   MatSolverTypeForSpecifcType handlers;
4492   MatSolverTypeHolder         next;
4493 };
4494 
4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4496 
4497 /*@C
4498    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4499 
4500    Input Parameters:
4501 +    package - name of the package, for example petsc or superlu
4502 .    mtype - the matrix type that works with this package
4503 .    ftype - the type of factorization supported by the package
4504 -    createfactor - routine that will create the factored matrix ready to be used
4505 
4506     Level: developer
4507 
4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4509 @*/
4510 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4511 {
4512   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4513   PetscBool                   flg;
4514   MatSolverTypeForSpecifcType inext, iprev = NULL;
4515 
4516   PetscFunctionBegin;
4517   PetscCall(MatInitializePackage());
4518   if (!next) {
4519     PetscCall(PetscNew(&MatSolverTypeHolders));
4520     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4521     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4522     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4523     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4524     PetscFunctionReturn(PETSC_SUCCESS);
4525   }
4526   while (next) {
4527     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4528     if (flg) {
4529       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4530       inext = next->handlers;
4531       while (inext) {
4532         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4533         if (flg) {
4534           inext->createfactor[(int)ftype - 1] = createfactor;
4535           PetscFunctionReturn(PETSC_SUCCESS);
4536         }
4537         iprev = inext;
4538         inext = inext->next;
4539       }
4540       PetscCall(PetscNew(&iprev->next));
4541       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4542       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4543       PetscFunctionReturn(PETSC_SUCCESS);
4544     }
4545     prev = next;
4546     next = next->next;
4547   }
4548   PetscCall(PetscNew(&prev->next));
4549   PetscCall(PetscStrallocpy(package, &prev->next->name));
4550   PetscCall(PetscNew(&prev->next->handlers));
4551   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4552   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4553   PetscFunctionReturn(PETSC_SUCCESS);
4554 }
4555 
4556 /*@C
4557    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4558 
4559    Input Parameters:
4560 +    type - name of the package, for example petsc or superlu
4561 .    ftype - the type of factorization supported by the type
4562 -    mtype - the matrix type that works with this type
4563 
4564    Output Parameters:
4565 +   foundtype - `PETSC_TRUE` if the type was registered
4566 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4567 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4568 
4569     Level: developer
4570 
4571 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4572 @*/
4573 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4574 {
4575   MatSolverTypeHolder         next = MatSolverTypeHolders;
4576   PetscBool                   flg;
4577   MatSolverTypeForSpecifcType inext;
4578 
4579   PetscFunctionBegin;
4580   if (foundtype) *foundtype = PETSC_FALSE;
4581   if (foundmtype) *foundmtype = PETSC_FALSE;
4582   if (createfactor) *createfactor = NULL;
4583 
4584   if (type) {
4585     while (next) {
4586       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4587       if (flg) {
4588         if (foundtype) *foundtype = PETSC_TRUE;
4589         inext = next->handlers;
4590         while (inext) {
4591           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4592           if (flg) {
4593             if (foundmtype) *foundmtype = PETSC_TRUE;
4594             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4595             PetscFunctionReturn(PETSC_SUCCESS);
4596           }
4597           inext = inext->next;
4598         }
4599       }
4600       next = next->next;
4601     }
4602   } else {
4603     while (next) {
4604       inext = next->handlers;
4605       while (inext) {
4606         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4607         if (flg && inext->createfactor[(int)ftype - 1]) {
4608           if (foundtype) *foundtype = PETSC_TRUE;
4609           if (foundmtype) *foundmtype = PETSC_TRUE;
4610           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4611           PetscFunctionReturn(PETSC_SUCCESS);
4612         }
4613         inext = inext->next;
4614       }
4615       next = next->next;
4616     }
4617     /* try with base classes inext->mtype */
4618     next = MatSolverTypeHolders;
4619     while (next) {
4620       inext = next->handlers;
4621       while (inext) {
4622         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4623         if (flg && inext->createfactor[(int)ftype - 1]) {
4624           if (foundtype) *foundtype = PETSC_TRUE;
4625           if (foundmtype) *foundmtype = PETSC_TRUE;
4626           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4627           PetscFunctionReturn(PETSC_SUCCESS);
4628         }
4629         inext = inext->next;
4630       }
4631       next = next->next;
4632     }
4633   }
4634   PetscFunctionReturn(PETSC_SUCCESS);
4635 }
4636 
4637 PetscErrorCode MatSolverTypeDestroy(void)
4638 {
4639   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4640   MatSolverTypeForSpecifcType inext, iprev;
4641 
4642   PetscFunctionBegin;
4643   while (next) {
4644     PetscCall(PetscFree(next->name));
4645     inext = next->handlers;
4646     while (inext) {
4647       PetscCall(PetscFree(inext->mtype));
4648       iprev = inext;
4649       inext = inext->next;
4650       PetscCall(PetscFree(iprev));
4651     }
4652     prev = next;
4653     next = next->next;
4654     PetscCall(PetscFree(prev));
4655   }
4656   MatSolverTypeHolders = NULL;
4657   PetscFunctionReturn(PETSC_SUCCESS);
4658 }
4659 
4660 /*@C
4661    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4662 
4663    Logically Collective
4664 
4665    Input Parameter:
4666 .  mat - the matrix
4667 
4668    Output Parameter:
4669 .  flg - `PETSC_TRUE` if uses the ordering
4670 
4671    Level: developer
4672 
4673    Note:
4674    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4675    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4676 
4677 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4678 @*/
4679 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4680 {
4681   PetscFunctionBegin;
4682   *flg = mat->canuseordering;
4683   PetscFunctionReturn(PETSC_SUCCESS);
4684 }
4685 
4686 /*@C
4687    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4688 
4689    Logically Collective
4690 
4691    Input Parameters:
4692 +  mat - the matrix obtained with `MatGetFactor()`
4693 -  ftype - the factorization type to be used
4694 
4695    Output Parameter:
4696 .  otype - the preferred ordering type
4697 
4698    Level: developer
4699 
4700 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4701 @*/
4702 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4703 {
4704   PetscFunctionBegin;
4705   *otype = mat->preferredordering[ftype];
4706   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4707   PetscFunctionReturn(PETSC_SUCCESS);
4708 }
4709 
4710 /*@C
4711    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4712 
4713    Collective
4714 
4715    Input Parameters:
4716 +  mat - the matrix
4717 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4718 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4719 
4720    Output Parameter:
4721 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4722 
4723    Options Database Key:
4724 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4725                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4726 
4727    Level: intermediate
4728 
4729    Notes:
4730      Users usually access the factorization solvers via `KSP`
4731 
4732       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4733      such as pastix, superlu, mumps etc.
4734 
4735       PETSc must have been ./configure to use the external solver, using the option --download-package
4736 
4737       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4738       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4739       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4740 
4741    Developer Note:
4742       This should actually be called `MatCreateFactor()` since it creates a new factor object
4743 
4744 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4745           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4746 @*/
4747 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4748 {
4749   PetscBool foundtype, foundmtype;
4750   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4751 
4752   PetscFunctionBegin;
4753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4754   PetscValidType(mat, 1);
4755 
4756   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4757   MatCheckPreallocated(mat, 1);
4758 
4759   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4760   if (!foundtype) {
4761     if (type) {
4762       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],
4763               ((PetscObject)mat)->type_name, type);
4764     } else {
4765       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);
4766     }
4767   }
4768   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4769   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);
4770 
4771   PetscCall((*conv)(mat, ftype, f));
4772   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4773   PetscFunctionReturn(PETSC_SUCCESS);
4774 }
4775 
4776 /*@C
4777    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4778 
4779    Not Collective
4780 
4781    Input Parameters:
4782 +  mat - the matrix
4783 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4784 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4785 
4786    Output Parameter:
4787 .    flg - PETSC_TRUE if the factorization is available
4788 
4789    Level: intermediate
4790 
4791    Notes:
4792       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4793      such as pastix, superlu, mumps etc.
4794 
4795       PETSc must have been ./configure to use the external solver, using the option --download-package
4796 
4797    Developer Note:
4798       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4799 
4800 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4801           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4802 @*/
4803 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4804 {
4805   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4806 
4807   PetscFunctionBegin;
4808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4809   PetscValidType(mat, 1);
4810   PetscValidBoolPointer(flg, 4);
4811 
4812   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4813   MatCheckPreallocated(mat, 1);
4814 
4815   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4816   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4817   PetscFunctionReturn(PETSC_SUCCESS);
4818 }
4819 
4820 /*@
4821    MatDuplicate - Duplicates a matrix including the non-zero structure.
4822 
4823    Collective
4824 
4825    Input Parameters:
4826 +  mat - the matrix
4827 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4828         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4829 
4830    Output Parameter:
4831 .  M - pointer to place new matrix
4832 
4833    Level: intermediate
4834 
4835    Notes:
4836     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4837 
4838     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.
4839 
4840     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
4841     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4842     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4843 
4844 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4845 @*/
4846 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4847 {
4848   Mat         B;
4849   VecType     vtype;
4850   PetscInt    i;
4851   PetscObject dm;
4852   void (*viewf)(void);
4853 
4854   PetscFunctionBegin;
4855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4856   PetscValidType(mat, 1);
4857   PetscValidPointer(M, 3);
4858   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4859   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4860   MatCheckPreallocated(mat, 1);
4861 
4862   *M = NULL;
4863   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4864   PetscUseTypeMethod(mat, duplicate, op, M);
4865   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4866   B = *M;
4867 
4868   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4869   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4870   PetscCall(MatGetVecType(mat, &vtype));
4871   PetscCall(MatSetVecType(B, vtype));
4872 
4873   B->stencil.dim = mat->stencil.dim;
4874   B->stencil.noc = mat->stencil.noc;
4875   for (i = 0; i <= mat->stencil.dim; i++) {
4876     B->stencil.dims[i]   = mat->stencil.dims[i];
4877     B->stencil.starts[i] = mat->stencil.starts[i];
4878   }
4879 
4880   B->nooffproczerorows = mat->nooffproczerorows;
4881   B->nooffprocentries  = mat->nooffprocentries;
4882 
4883   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4884   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4885   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4886   PetscFunctionReturn(PETSC_SUCCESS);
4887 }
4888 
4889 /*@
4890    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4891 
4892    Logically Collective
4893 
4894    Input Parameter:
4895 .  mat - the matrix
4896 
4897    Output Parameter:
4898 .  v - the diagonal of the matrix
4899 
4900    Level: intermediate
4901 
4902    Note:
4903    Currently only correct in parallel for square matrices.
4904 
4905 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4906 @*/
4907 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4908 {
4909   PetscFunctionBegin;
4910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4911   PetscValidType(mat, 1);
4912   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4913   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4914   MatCheckPreallocated(mat, 1);
4915 
4916   PetscUseTypeMethod(mat, getdiagonal, v);
4917   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4918   PetscFunctionReturn(PETSC_SUCCESS);
4919 }
4920 
4921 /*@C
4922    MatGetRowMin - Gets the minimum value (of the real part) of each
4923         row of the matrix
4924 
4925    Logically Collective
4926 
4927    Input Parameter:
4928 .  mat - the matrix
4929 
4930    Output Parameters:
4931 +  v - the vector for storing the maximums
4932 -  idx - the indices of the column found for each row (optional)
4933 
4934    Level: intermediate
4935 
4936    Note:
4937     The result of this call are the same as if one converted the matrix to dense format
4938       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4939 
4940     This code is only implemented for a couple of matrix formats.
4941 
4942 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4943           `MatGetRowMax()`
4944 @*/
4945 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4946 {
4947   PetscFunctionBegin;
4948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4949   PetscValidType(mat, 1);
4950   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4951   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4952 
4953   if (!mat->cmap->N) {
4954     PetscCall(VecSet(v, PETSC_MAX_REAL));
4955     if (idx) {
4956       PetscInt i, m = mat->rmap->n;
4957       for (i = 0; i < m; i++) idx[i] = -1;
4958     }
4959   } else {
4960     MatCheckPreallocated(mat, 1);
4961   }
4962   PetscUseTypeMethod(mat, getrowmin, v, idx);
4963   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4964   PetscFunctionReturn(PETSC_SUCCESS);
4965 }
4966 
4967 /*@C
4968    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4969         row of the matrix
4970 
4971    Logically Collective
4972 
4973    Input Parameter:
4974 .  mat - the matrix
4975 
4976    Output Parameters:
4977 +  v - the vector for storing the minimums
4978 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4979 
4980    Level: intermediate
4981 
4982    Notes:
4983     if a row is completely empty or has only 0.0 values then the idx[] value for that
4984     row is 0 (the first column).
4985 
4986     This code is only implemented for a couple of matrix formats.
4987 
4988 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4989 @*/
4990 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4991 {
4992   PetscFunctionBegin;
4993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4994   PetscValidType(mat, 1);
4995   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4996   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4997   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4998 
4999   if (!mat->cmap->N) {
5000     PetscCall(VecSet(v, 0.0));
5001     if (idx) {
5002       PetscInt i, m = mat->rmap->n;
5003       for (i = 0; i < m; i++) idx[i] = -1;
5004     }
5005   } else {
5006     MatCheckPreallocated(mat, 1);
5007     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5008     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5009   }
5010   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5011   PetscFunctionReturn(PETSC_SUCCESS);
5012 }
5013 
5014 /*@C
5015    MatGetRowMax - Gets the maximum value (of the real part) of each
5016         row of the matrix
5017 
5018    Logically Collective
5019 
5020    Input Parameter:
5021 .  mat - the matrix
5022 
5023    Output Parameters:
5024 +  v - the vector for storing the maximums
5025 -  idx - the indices of the column found for each row (optional)
5026 
5027    Level: intermediate
5028 
5029    Notes:
5030     The result of this call are the same as if one converted the matrix to dense format
5031       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5032 
5033     This code is only implemented for a couple of matrix formats.
5034 
5035 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5036 @*/
5037 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5038 {
5039   PetscFunctionBegin;
5040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5041   PetscValidType(mat, 1);
5042   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5043   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5044 
5045   if (!mat->cmap->N) {
5046     PetscCall(VecSet(v, PETSC_MIN_REAL));
5047     if (idx) {
5048       PetscInt i, m = mat->rmap->n;
5049       for (i = 0; i < m; i++) idx[i] = -1;
5050     }
5051   } else {
5052     MatCheckPreallocated(mat, 1);
5053     PetscUseTypeMethod(mat, getrowmax, v, idx);
5054   }
5055   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5056   PetscFunctionReturn(PETSC_SUCCESS);
5057 }
5058 
5059 /*@C
5060    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5061         row of the matrix
5062 
5063    Logically Collective
5064 
5065    Input Parameter:
5066 .  mat - the matrix
5067 
5068    Output Parameters:
5069 +  v - the vector for storing the maximums
5070 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5071 
5072    Level: intermediate
5073 
5074    Notes:
5075     if a row is completely empty or has only 0.0 values then the idx[] value for that
5076     row is 0 (the first column).
5077 
5078     This code is only implemented for a couple of matrix formats.
5079 
5080 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5081 @*/
5082 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5083 {
5084   PetscFunctionBegin;
5085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5086   PetscValidType(mat, 1);
5087   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5088   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5089 
5090   if (!mat->cmap->N) {
5091     PetscCall(VecSet(v, 0.0));
5092     if (idx) {
5093       PetscInt i, m = mat->rmap->n;
5094       for (i = 0; i < m; i++) idx[i] = -1;
5095     }
5096   } else {
5097     MatCheckPreallocated(mat, 1);
5098     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5099     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5100   }
5101   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5102   PetscFunctionReturn(PETSC_SUCCESS);
5103 }
5104 
5105 /*@
5106    MatGetRowSum - Gets the sum of each row of the matrix
5107 
5108    Logically or Neighborhood Collective
5109 
5110    Input Parameter:
5111 .  mat - the matrix
5112 
5113    Output Parameter:
5114 .  v - the vector for storing the sum of rows
5115 
5116    Level: intermediate
5117 
5118    Notes:
5119     This code is slow since it is not currently specialized for different formats
5120 
5121 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5122 @*/
5123 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5124 {
5125   Vec ones;
5126 
5127   PetscFunctionBegin;
5128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5129   PetscValidType(mat, 1);
5130   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5131   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5132   MatCheckPreallocated(mat, 1);
5133   PetscCall(MatCreateVecs(mat, &ones, NULL));
5134   PetscCall(VecSet(ones, 1.));
5135   PetscCall(MatMult(mat, ones, v));
5136   PetscCall(VecDestroy(&ones));
5137   PetscFunctionReturn(PETSC_SUCCESS);
5138 }
5139 
5140 /*@
5141    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5142    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5143 
5144    Collective
5145 
5146    Input Parameter:
5147 .  mat - the matrix to provide the transpose
5148 
5149    Output Parameter:
5150 .  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
5151 
5152    Level: advanced
5153 
5154    Note:
5155    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
5156    routine allows bypassing that call.
5157 
5158 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5159 @*/
5160 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5161 {
5162   PetscContainer  rB = NULL;
5163   MatParentState *rb = NULL;
5164 
5165   PetscFunctionBegin;
5166   PetscCall(PetscNew(&rb));
5167   rb->id    = ((PetscObject)mat)->id;
5168   rb->state = 0;
5169   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5170   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5171   PetscCall(PetscContainerSetPointer(rB, rb));
5172   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5173   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5174   PetscCall(PetscObjectDereference((PetscObject)rB));
5175   PetscFunctionReturn(PETSC_SUCCESS);
5176 }
5177 
5178 /*@
5179    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5180 
5181    Collective
5182 
5183    Input Parameters:
5184 +  mat - the matrix to transpose
5185 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5186 
5187    Output Parameter:
5188 .  B - the transpose
5189 
5190    Level: intermediate
5191 
5192    Notes:
5193      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5194 
5195      `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
5196      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5197 
5198      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.
5199 
5200      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5201 
5202      If mat is unchanged from the last call this function returns immediately without recomputing the result
5203 
5204      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5205 
5206 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5207           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5208 @*/
5209 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5210 {
5211   PetscContainer  rB = NULL;
5212   MatParentState *rb = NULL;
5213 
5214   PetscFunctionBegin;
5215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5216   PetscValidType(mat, 1);
5217   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5218   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5219   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5220   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5221   MatCheckPreallocated(mat, 1);
5222   if (reuse == MAT_REUSE_MATRIX) {
5223     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5224     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5225     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5226     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5227     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5228   }
5229 
5230   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5231   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5232     PetscUseTypeMethod(mat, transpose, reuse, B);
5233     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5234   }
5235   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5236 
5237   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5238   if (reuse != MAT_INPLACE_MATRIX) {
5239     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5240     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5241     rb->state        = ((PetscObject)mat)->state;
5242     rb->nonzerostate = mat->nonzerostate;
5243   }
5244   PetscFunctionReturn(PETSC_SUCCESS);
5245 }
5246 
5247 /*@
5248    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5249 
5250    Collective
5251 
5252    Input Parameter:
5253 .  A - the matrix to transpose
5254 
5255    Output Parameter:
5256 .  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
5257       numerical portion.
5258 
5259    Level: intermediate
5260 
5261    Note:
5262    This is not supported for many matrix types, use `MatTranspose()` in those cases
5263 
5264 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5265 @*/
5266 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5267 {
5268   PetscFunctionBegin;
5269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5270   PetscValidType(A, 1);
5271   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5272   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5273   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5274   PetscUseTypeMethod(A, transposesymbolic, B);
5275   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5276 
5277   PetscCall(MatTransposeSetPrecursor(A, *B));
5278   PetscFunctionReturn(PETSC_SUCCESS);
5279 }
5280 
5281 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5282 {
5283   PetscContainer  rB;
5284   MatParentState *rb;
5285 
5286   PetscFunctionBegin;
5287   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5288   PetscValidType(A, 1);
5289   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5290   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5291   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5292   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5293   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5294   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5295   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5296   PetscFunctionReturn(PETSC_SUCCESS);
5297 }
5298 
5299 /*@
5300    MatIsTranspose - Test whether a matrix is another one's transpose,
5301         or its own, in which case it tests symmetry.
5302 
5303    Collective
5304 
5305    Input Parameters:
5306 +  A - the matrix to test
5307 .  B - the matrix to test against, this can equal the first parameter
5308 -  tol - tolerance, differences between entries smaller than this are counted as zero
5309 
5310    Output Parameter:
5311 .  flg - the result
5312 
5313    Level: intermediate
5314 
5315    Notes:
5316    Only available for `MATAIJ` matrices.
5317 
5318    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5319    test involves parallel copies of the block-offdiagonal parts of the matrix.
5320 
5321 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5322 @*/
5323 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5324 {
5325   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5326 
5327   PetscFunctionBegin;
5328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5329   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5330   PetscValidBoolPointer(flg, 4);
5331   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5332   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5333   *flg = PETSC_FALSE;
5334   if (f && g) {
5335     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5336     PetscCall((*f)(A, B, tol, flg));
5337   } else {
5338     MatType mattype;
5339 
5340     PetscCall(MatGetType(f ? B : A, &mattype));
5341     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5342   }
5343   PetscFunctionReturn(PETSC_SUCCESS);
5344 }
5345 
5346 /*@
5347    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5348 
5349    Collective
5350 
5351    Input Parameters:
5352 +  mat - the matrix to transpose and complex conjugate
5353 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5354 
5355    Output Parameter:
5356 .  B - the Hermitian transpose
5357 
5358    Level: intermediate
5359 
5360 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5361 @*/
5362 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5363 {
5364   PetscFunctionBegin;
5365   PetscCall(MatTranspose(mat, reuse, B));
5366 #if defined(PETSC_USE_COMPLEX)
5367   PetscCall(MatConjugate(*B));
5368 #endif
5369   PetscFunctionReturn(PETSC_SUCCESS);
5370 }
5371 
5372 /*@
5373    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5374 
5375    Collective
5376 
5377    Input Parameters:
5378 +  A - the matrix to test
5379 .  B - the matrix to test against, this can equal the first parameter
5380 -  tol - tolerance, differences between entries smaller than this are counted as zero
5381 
5382    Output Parameter:
5383 .  flg - the result
5384 
5385    Level: intermediate
5386 
5387    Notes:
5388    Only available for `MATAIJ` matrices.
5389 
5390    The sequential algorithm
5391    has a running time of the order of the number of nonzeros; the parallel
5392    test involves parallel copies of the block-offdiagonal parts of the matrix.
5393 
5394 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5395 @*/
5396 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5397 {
5398   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5399 
5400   PetscFunctionBegin;
5401   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5402   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5403   PetscValidBoolPointer(flg, 4);
5404   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5405   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5406   if (f && g) {
5407     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5408     PetscCall((*f)(A, B, tol, flg));
5409   }
5410   PetscFunctionReturn(PETSC_SUCCESS);
5411 }
5412 
5413 /*@
5414    MatPermute - Creates a new matrix with rows and columns permuted from the
5415    original.
5416 
5417    Collective
5418 
5419    Input Parameters:
5420 +  mat - the matrix to permute
5421 .  row - row permutation, each processor supplies only the permutation for its rows
5422 -  col - column permutation, each processor supplies only the permutation for its columns
5423 
5424    Output Parameter:
5425 .  B - the permuted matrix
5426 
5427    Level: advanced
5428 
5429    Note:
5430    The index sets map from row/col of permuted matrix to row/col of original matrix.
5431    The index sets should be on the same communicator as mat and have the same local sizes.
5432 
5433    Developer Note:
5434      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5435      exploit the fact that row and col are permutations, consider implementing the
5436      more general `MatCreateSubMatrix()` instead.
5437 
5438 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5439 @*/
5440 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5441 {
5442   PetscFunctionBegin;
5443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5444   PetscValidType(mat, 1);
5445   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5446   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5447   PetscValidPointer(B, 4);
5448   PetscCheckSameComm(mat, 1, row, 2);
5449   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5450   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5451   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5452   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5453   MatCheckPreallocated(mat, 1);
5454 
5455   if (mat->ops->permute) {
5456     PetscUseTypeMethod(mat, permute, row, col, B);
5457     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5458   } else {
5459     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5460   }
5461   PetscFunctionReturn(PETSC_SUCCESS);
5462 }
5463 
5464 /*@
5465    MatEqual - Compares two matrices.
5466 
5467    Collective
5468 
5469    Input Parameters:
5470 +  A - the first matrix
5471 -  B - the second matrix
5472 
5473    Output Parameter:
5474 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5475 
5476    Level: intermediate
5477 
5478 .seealso: [](ch_matrices), `Mat`
5479 @*/
5480 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5481 {
5482   PetscFunctionBegin;
5483   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5484   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5485   PetscValidType(A, 1);
5486   PetscValidType(B, 2);
5487   PetscValidBoolPointer(flg, 3);
5488   PetscCheckSameComm(A, 1, B, 2);
5489   MatCheckPreallocated(A, 1);
5490   MatCheckPreallocated(B, 2);
5491   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5492   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5493   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,
5494              B->cmap->N);
5495   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5496     PetscUseTypeMethod(A, equal, B, flg);
5497   } else {
5498     PetscCall(MatMultEqual(A, B, 10, flg));
5499   }
5500   PetscFunctionReturn(PETSC_SUCCESS);
5501 }
5502 
5503 /*@
5504    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5505    matrices that are stored as vectors.  Either of the two scaling
5506    matrices can be `NULL`.
5507 
5508    Collective
5509 
5510    Input Parameters:
5511 +  mat - the matrix to be scaled
5512 .  l - the left scaling vector (or `NULL`)
5513 -  r - the right scaling vector (or `NULL`)
5514 
5515    Level: intermediate
5516 
5517    Note:
5518    `MatDiagonalScale()` computes A = LAR, where
5519    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5520    The L scales the rows of the matrix, the R scales the columns of the matrix.
5521 
5522 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5523 @*/
5524 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5525 {
5526   PetscFunctionBegin;
5527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5528   PetscValidType(mat, 1);
5529   if (l) {
5530     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5531     PetscCheckSameComm(mat, 1, l, 2);
5532   }
5533   if (r) {
5534     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5535     PetscCheckSameComm(mat, 1, r, 3);
5536   }
5537   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5538   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5539   MatCheckPreallocated(mat, 1);
5540   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5541 
5542   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5543   PetscUseTypeMethod(mat, diagonalscale, l, r);
5544   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5545   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5546   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5547   PetscFunctionReturn(PETSC_SUCCESS);
5548 }
5549 
5550 /*@
5551     MatScale - Scales all elements of a matrix by a given number.
5552 
5553     Logically Collective
5554 
5555     Input Parameters:
5556 +   mat - the matrix to be scaled
5557 -   a  - the scaling value
5558 
5559     Level: intermediate
5560 
5561 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5562 @*/
5563 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5564 {
5565   PetscFunctionBegin;
5566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5567   PetscValidType(mat, 1);
5568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5570   PetscValidLogicalCollectiveScalar(mat, a, 2);
5571   MatCheckPreallocated(mat, 1);
5572 
5573   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5574   if (a != (PetscScalar)1.0) {
5575     PetscUseTypeMethod(mat, scale, a);
5576     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5577   }
5578   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5579   PetscFunctionReturn(PETSC_SUCCESS);
5580 }
5581 
5582 /*@
5583    MatNorm - Calculates various norms of a matrix.
5584 
5585    Collective
5586 
5587    Input Parameters:
5588 +  mat - the matrix
5589 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5590 
5591    Output Parameter:
5592 .  nrm - the resulting norm
5593 
5594    Level: intermediate
5595 
5596 .seealso: [](ch_matrices), `Mat`
5597 @*/
5598 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5599 {
5600   PetscFunctionBegin;
5601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5602   PetscValidType(mat, 1);
5603   PetscValidRealPointer(nrm, 3);
5604 
5605   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5606   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5607   MatCheckPreallocated(mat, 1);
5608 
5609   PetscUseTypeMethod(mat, norm, type, nrm);
5610   PetscFunctionReturn(PETSC_SUCCESS);
5611 }
5612 
5613 /*
5614      This variable is used to prevent counting of MatAssemblyBegin() that
5615    are called from within a MatAssemblyEnd().
5616 */
5617 static PetscInt MatAssemblyEnd_InUse = 0;
5618 /*@
5619    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5620    be called after completing all calls to `MatSetValues()`.
5621 
5622    Collective
5623 
5624    Input Parameters:
5625 +  mat - the matrix
5626 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5627 
5628    Level: beginner
5629 
5630    Notes:
5631    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5632    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5633 
5634    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5635    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5636    using the matrix.
5637 
5638    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5639    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
5640    a global collective operation requiring all processes that share the matrix.
5641 
5642    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5643    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5644    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5645 
5646 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5647 @*/
5648 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5649 {
5650   PetscFunctionBegin;
5651   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5652   PetscValidType(mat, 1);
5653   MatCheckPreallocated(mat, 1);
5654   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5655   if (mat->assembled) {
5656     mat->was_assembled = PETSC_TRUE;
5657     mat->assembled     = PETSC_FALSE;
5658   }
5659 
5660   if (!MatAssemblyEnd_InUse) {
5661     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5662     PetscTryTypeMethod(mat, assemblybegin, type);
5663     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5664   } else PetscTryTypeMethod(mat, assemblybegin, type);
5665   PetscFunctionReturn(PETSC_SUCCESS);
5666 }
5667 
5668 /*@
5669    MatAssembled - Indicates if a matrix has been assembled and is ready for
5670      use; for example, in matrix-vector product.
5671 
5672    Not Collective
5673 
5674    Input Parameter:
5675 .  mat - the matrix
5676 
5677    Output Parameter:
5678 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5679 
5680    Level: advanced
5681 
5682 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5683 @*/
5684 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5685 {
5686   PetscFunctionBegin;
5687   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5688   PetscValidBoolPointer(assembled, 2);
5689   *assembled = mat->assembled;
5690   PetscFunctionReturn(PETSC_SUCCESS);
5691 }
5692 
5693 /*@
5694    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5695    be called after `MatAssemblyBegin()`.
5696 
5697    Collective
5698 
5699    Input Parameters:
5700 +  mat - the matrix
5701 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5702 
5703    Options Database Keys:
5704 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5705 .  -mat_view ::ascii_info_detail - Prints more detailed info
5706 .  -mat_view - Prints matrix in ASCII format
5707 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5708 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5709 .  -display <name> - Sets display name (default is host)
5710 .  -draw_pause <sec> - Sets number of seconds to pause after display
5711 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5712 .  -viewer_socket_machine <machine> - Machine to use for socket
5713 .  -viewer_socket_port <port> - Port number to use for socket
5714 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5715 
5716    Level: beginner
5717 
5718 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5719 @*/
5720 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5721 {
5722   static PetscInt inassm = 0;
5723   PetscBool       flg    = PETSC_FALSE;
5724 
5725   PetscFunctionBegin;
5726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5727   PetscValidType(mat, 1);
5728 
5729   inassm++;
5730   MatAssemblyEnd_InUse++;
5731   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5732     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5733     PetscTryTypeMethod(mat, assemblyend, type);
5734     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5735   } else PetscTryTypeMethod(mat, assemblyend, type);
5736 
5737   /* Flush assembly is not a true assembly */
5738   if (type != MAT_FLUSH_ASSEMBLY) {
5739     if (mat->num_ass) {
5740       if (!mat->symmetry_eternal) {
5741         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5742         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5743       }
5744       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5745       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5746     }
5747     mat->num_ass++;
5748     mat->assembled        = PETSC_TRUE;
5749     mat->ass_nonzerostate = mat->nonzerostate;
5750   }
5751 
5752   mat->insertmode = NOT_SET_VALUES;
5753   MatAssemblyEnd_InUse--;
5754   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5755   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5756     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5757 
5758     if (mat->checksymmetryonassembly) {
5759       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5760       if (flg) {
5761         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5762       } else {
5763         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5764       }
5765     }
5766     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5767   }
5768   inassm--;
5769   PetscFunctionReturn(PETSC_SUCCESS);
5770 }
5771 
5772 /*@
5773    MatSetOption - Sets a parameter option for a matrix. Some options
5774    may be specific to certain storage formats.  Some options
5775    determine how values will be inserted (or added). Sorted,
5776    row-oriented input will generally assemble the fastest. The default
5777    is row-oriented.
5778 
5779    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5780 
5781    Input Parameters:
5782 +  mat - the matrix
5783 .  option - the option, one of those listed below (and possibly others),
5784 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5785 
5786   Options Describing Matrix Structure:
5787 +    `MAT_SPD` - symmetric positive definite
5788 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5789 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5790 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5791 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5792 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5793 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5794 
5795    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5796    do not need to be computed (usually at a high cost)
5797 
5798    Options For Use with `MatSetValues()`:
5799    Insert a logically dense subblock, which can be
5800 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5801 
5802    These options reflect the data you pass in with `MatSetValues()`; it has
5803    nothing to do with how the data is stored internally in the matrix
5804    data structure.
5805 
5806    When (re)assembling a matrix, we can restrict the input for
5807    efficiency/debugging purposes.  These options include
5808 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5809 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5810 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5811 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5812 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5813 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5814         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5815         performance for very large process counts.
5816 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5817         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5818         functions, instead sending only neighbor messages.
5819 
5820    Level: intermediate
5821 
5822    Notes:
5823    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5824 
5825    Some options are relevant only for particular matrix types and
5826    are thus ignored by others.  Other options are not supported by
5827    certain matrix types and will generate an error message if set.
5828 
5829    If using Fortran to compute a matrix, one may need to
5830    use the column-oriented option (or convert to the row-oriented
5831    format).
5832 
5833    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5834    that would generate a new entry in the nonzero structure is instead
5835    ignored.  Thus, if memory has not already been allocated for this particular
5836    data, then the insertion is ignored. For dense matrices, in which
5837    the entire array is allocated, no entries are ever ignored.
5838    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5839 
5840    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5841    that would generate a new entry in the nonzero structure instead produces
5842    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
5843 
5844    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5845    that would generate a new entry that has not been preallocated will
5846    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5847    only.) This is a useful flag when debugging matrix memory preallocation.
5848    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5849 
5850    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5851    other processors should be dropped, rather than stashed.
5852    This is useful if you know that the "owning" processor is also
5853    always generating the correct matrix entries, so that PETSc need
5854    not transfer duplicate entries generated on another processor.
5855 
5856    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5857    searches during matrix assembly. When this flag is set, the hash table
5858    is created during the first matrix assembly. This hash table is
5859    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5860    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5861    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5862    supported by `MATMPIBAIJ` format only.
5863 
5864    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5865    are kept in the nonzero structure
5866 
5867    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5868    a zero location in the matrix
5869 
5870    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5871 
5872    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5873         zero row routines and thus improves performance for very large process counts.
5874 
5875    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5876         part of the matrix (since they should match the upper triangular part).
5877 
5878    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5879                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5880                      with finite difference schemes with non-periodic boundary conditions.
5881 
5882    Developer Note:
5883    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5884    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5885    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5886    not changed.
5887 
5888 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5889 @*/
5890 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5891 {
5892   PetscFunctionBegin;
5893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5894   if (op > 0) {
5895     PetscValidLogicalCollectiveEnum(mat, op, 2);
5896     PetscValidLogicalCollectiveBool(mat, flg, 3);
5897   }
5898 
5899   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);
5900 
5901   switch (op) {
5902   case MAT_FORCE_DIAGONAL_ENTRIES:
5903     mat->force_diagonals = flg;
5904     PetscFunctionReturn(PETSC_SUCCESS);
5905   case MAT_NO_OFF_PROC_ENTRIES:
5906     mat->nooffprocentries = flg;
5907     PetscFunctionReturn(PETSC_SUCCESS);
5908   case MAT_SUBSET_OFF_PROC_ENTRIES:
5909     mat->assembly_subset = flg;
5910     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5911 #if !defined(PETSC_HAVE_MPIUNI)
5912       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5913 #endif
5914       mat->stash.first_assembly_done = PETSC_FALSE;
5915     }
5916     PetscFunctionReturn(PETSC_SUCCESS);
5917   case MAT_NO_OFF_PROC_ZERO_ROWS:
5918     mat->nooffproczerorows = flg;
5919     PetscFunctionReturn(PETSC_SUCCESS);
5920   case MAT_SPD:
5921     if (flg) {
5922       mat->spd                    = PETSC_BOOL3_TRUE;
5923       mat->symmetric              = PETSC_BOOL3_TRUE;
5924       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5925     } else {
5926       mat->spd = PETSC_BOOL3_FALSE;
5927     }
5928     break;
5929   case MAT_SYMMETRIC:
5930     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5931     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5932 #if !defined(PETSC_USE_COMPLEX)
5933     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5934 #endif
5935     break;
5936   case MAT_HERMITIAN:
5937     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5938     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5939 #if !defined(PETSC_USE_COMPLEX)
5940     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5941 #endif
5942     break;
5943   case MAT_STRUCTURALLY_SYMMETRIC:
5944     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5945     break;
5946   case MAT_SYMMETRY_ETERNAL:
5947     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");
5948     mat->symmetry_eternal = flg;
5949     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5950     break;
5951   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5952     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");
5953     mat->structural_symmetry_eternal = flg;
5954     break;
5955   case MAT_SPD_ETERNAL:
5956     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");
5957     mat->spd_eternal = flg;
5958     if (flg) {
5959       mat->structural_symmetry_eternal = PETSC_TRUE;
5960       mat->symmetry_eternal            = PETSC_TRUE;
5961     }
5962     break;
5963   case MAT_STRUCTURE_ONLY:
5964     mat->structure_only = flg;
5965     break;
5966   case MAT_SORTED_FULL:
5967     mat->sortedfull = flg;
5968     break;
5969   default:
5970     break;
5971   }
5972   PetscTryTypeMethod(mat, setoption, op, flg);
5973   PetscFunctionReturn(PETSC_SUCCESS);
5974 }
5975 
5976 /*@
5977    MatGetOption - Gets a parameter option that has been set for a matrix.
5978 
5979    Logically Collective
5980 
5981    Input Parameters:
5982 +  mat - the matrix
5983 -  option - the option, this only responds to certain options, check the code for which ones
5984 
5985    Output Parameter:
5986 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5987 
5988    Level: intermediate
5989 
5990     Notes:
5991     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5992 
5993     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5994     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5995 
5996 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5997     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5998 @*/
5999 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6000 {
6001   PetscFunctionBegin;
6002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6003   PetscValidType(mat, 1);
6004 
6005   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);
6006   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()");
6007 
6008   switch (op) {
6009   case MAT_NO_OFF_PROC_ENTRIES:
6010     *flg = mat->nooffprocentries;
6011     break;
6012   case MAT_NO_OFF_PROC_ZERO_ROWS:
6013     *flg = mat->nooffproczerorows;
6014     break;
6015   case MAT_SYMMETRIC:
6016     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6017     break;
6018   case MAT_HERMITIAN:
6019     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6020     break;
6021   case MAT_STRUCTURALLY_SYMMETRIC:
6022     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6023     break;
6024   case MAT_SPD:
6025     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6026     break;
6027   case MAT_SYMMETRY_ETERNAL:
6028     *flg = mat->symmetry_eternal;
6029     break;
6030   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6031     *flg = mat->symmetry_eternal;
6032     break;
6033   default:
6034     break;
6035   }
6036   PetscFunctionReturn(PETSC_SUCCESS);
6037 }
6038 
6039 /*@
6040    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6041    this routine retains the old nonzero structure.
6042 
6043    Logically Collective
6044 
6045    Input Parameter:
6046 .  mat - the matrix
6047 
6048    Level: intermediate
6049 
6050    Note:
6051     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.
6052    See the Performance chapter of the users manual for information on preallocating matrices.
6053 
6054 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6055 @*/
6056 PetscErrorCode MatZeroEntries(Mat mat)
6057 {
6058   PetscFunctionBegin;
6059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6060   PetscValidType(mat, 1);
6061   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6062   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");
6063   MatCheckPreallocated(mat, 1);
6064 
6065   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6066   PetscUseTypeMethod(mat, zeroentries);
6067   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6068   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6069   PetscFunctionReturn(PETSC_SUCCESS);
6070 }
6071 
6072 /*@
6073    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6074    of a set of rows and columns of a matrix.
6075 
6076    Collective
6077 
6078    Input Parameters:
6079 +  mat - the matrix
6080 .  numRows - the number of rows/columns to zero
6081 .  rows - the global row indices
6082 .  diag - value put in the diagonal of the eliminated rows
6083 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6084 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6085 
6086    Level: intermediate
6087 
6088    Notes:
6089    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6090 
6091    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6092    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
6093 
6094    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6095    Krylov method to take advantage of the known solution on the zeroed rows.
6096 
6097    For the parallel case, all processes that share the matrix (i.e.,
6098    those in the communicator used for matrix creation) MUST call this
6099    routine, regardless of whether any rows being zeroed are owned by
6100    them.
6101 
6102    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6103 
6104    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6105    list only rows local to itself).
6106 
6107    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6108 
6109 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6110           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6111 @*/
6112 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6113 {
6114   PetscFunctionBegin;
6115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6116   PetscValidType(mat, 1);
6117   if (numRows) PetscValidIntPointer(rows, 3);
6118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6119   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6120   MatCheckPreallocated(mat, 1);
6121 
6122   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6123   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6124   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6125   PetscFunctionReturn(PETSC_SUCCESS);
6126 }
6127 
6128 /*@
6129    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6130    of a set of rows and columns of a matrix.
6131 
6132    Collective
6133 
6134    Input Parameters:
6135 +  mat - the matrix
6136 .  is - the rows to zero
6137 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6138 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6139 -  b - optional vector of right hand side, that will be adjusted by provided solution
6140 
6141    Level: intermediate
6142 
6143    Note:
6144    See `MatZeroRowsColumns()` for details on how this routine operates.
6145 
6146 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6147           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6148 @*/
6149 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6150 {
6151   PetscInt        numRows;
6152   const PetscInt *rows;
6153 
6154   PetscFunctionBegin;
6155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6156   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6157   PetscValidType(mat, 1);
6158   PetscValidType(is, 2);
6159   PetscCall(ISGetLocalSize(is, &numRows));
6160   PetscCall(ISGetIndices(is, &rows));
6161   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6162   PetscCall(ISRestoreIndices(is, &rows));
6163   PetscFunctionReturn(PETSC_SUCCESS);
6164 }
6165 
6166 /*@
6167    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6168    of a set of rows of a matrix.
6169 
6170    Collective
6171 
6172    Input Parameters:
6173 +  mat - the matrix
6174 .  numRows - the number of rows to zero
6175 .  rows - the global row indices
6176 .  diag - value put in the diagonal of the zeroed rows
6177 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6178 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6179 
6180    Level: intermediate
6181 
6182    Notes:
6183    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6184 
6185    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6186 
6187    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6188    Krylov method to take advantage of the known solution on the zeroed rows.
6189 
6190    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)
6191    from the matrix.
6192 
6193    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6194    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
6195    formats this does not alter the nonzero structure.
6196 
6197    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6198    of the matrix is not changed the values are
6199    merely zeroed.
6200 
6201    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6202    formats can optionally remove the main diagonal entry from the
6203    nonzero structure as well, by passing 0.0 as the final argument).
6204 
6205    For the parallel case, all processes that share the matrix (i.e.,
6206    those in the communicator used for matrix creation) MUST call this
6207    routine, regardless of whether any rows being zeroed are owned by
6208    them.
6209 
6210    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6211    list only rows local to itself).
6212 
6213    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6214    owns that are to be zeroed. This saves a global synchronization in the implementation.
6215 
6216 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6217           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6218 @*/
6219 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6220 {
6221   PetscFunctionBegin;
6222   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6223   PetscValidType(mat, 1);
6224   if (numRows) PetscValidIntPointer(rows, 3);
6225   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6226   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6227   MatCheckPreallocated(mat, 1);
6228 
6229   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6230   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6231   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6232   PetscFunctionReturn(PETSC_SUCCESS);
6233 }
6234 
6235 /*@
6236    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6237    of a set of rows of a matrix.
6238 
6239    Collective
6240 
6241    Input Parameters:
6242 +  mat - the matrix
6243 .  is - index set of rows to remove (if `NULL` then no row is removed)
6244 .  diag - value put in all diagonals of eliminated rows
6245 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6246 -  b - optional vector of right hand side, that will be adjusted by provided solution
6247 
6248    Level: intermediate
6249 
6250    Note:
6251    See `MatZeroRows()` for details on how this routine operates.
6252 
6253 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6254           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6255 @*/
6256 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6257 {
6258   PetscInt        numRows = 0;
6259   const PetscInt *rows    = NULL;
6260 
6261   PetscFunctionBegin;
6262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6263   PetscValidType(mat, 1);
6264   if (is) {
6265     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6266     PetscCall(ISGetLocalSize(is, &numRows));
6267     PetscCall(ISGetIndices(is, &rows));
6268   }
6269   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6270   if (is) PetscCall(ISRestoreIndices(is, &rows));
6271   PetscFunctionReturn(PETSC_SUCCESS);
6272 }
6273 
6274 /*@
6275    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6276    of a set of rows of a matrix. These rows must be local to the process.
6277 
6278    Collective
6279 
6280    Input Parameters:
6281 +  mat - the matrix
6282 .  numRows - the number of rows to remove
6283 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6284 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6285 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6286 -  b - optional vector of right hand side, that will be adjusted by provided solution
6287 
6288    Level: intermediate
6289 
6290    Notes:
6291    See `MatZeroRows()` for details on how this routine operates.
6292 
6293    The grid coordinates are across the entire grid, not just the local portion
6294 
6295    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6296    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6297    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6298    `DM_BOUNDARY_PERIODIC` boundary type.
6299 
6300    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
6301    a single value per point) you can skip filling those indices.
6302 
6303    Fortran Note:
6304    `idxm` and `idxn` should be declared as
6305 $     MatStencil idxm(4, m)
6306    and the values inserted using
6307 .vb
6308     idxm(MatStencil_i, 1) = i
6309     idxm(MatStencil_j, 1) = j
6310     idxm(MatStencil_k, 1) = k
6311     idxm(MatStencil_c, 1) = c
6312    etc
6313 .ve
6314 
6315 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6316           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6317 @*/
6318 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6319 {
6320   PetscInt  dim    = mat->stencil.dim;
6321   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6322   PetscInt *dims   = mat->stencil.dims + 1;
6323   PetscInt *starts = mat->stencil.starts;
6324   PetscInt *dxm    = (PetscInt *)rows;
6325   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6326 
6327   PetscFunctionBegin;
6328   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6329   PetscValidType(mat, 1);
6330   if (numRows) PetscValidPointer(rows, 3);
6331 
6332   PetscCall(PetscMalloc1(numRows, &jdxm));
6333   for (i = 0; i < numRows; ++i) {
6334     /* Skip unused dimensions (they are ordered k, j, i, c) */
6335     for (j = 0; j < 3 - sdim; ++j) dxm++;
6336     /* Local index in X dir */
6337     tmp = *dxm++ - starts[0];
6338     /* Loop over remaining dimensions */
6339     for (j = 0; j < dim - 1; ++j) {
6340       /* If nonlocal, set index to be negative */
6341       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6342       /* Update local index */
6343       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6344     }
6345     /* Skip component slot if necessary */
6346     if (mat->stencil.noc) dxm++;
6347     /* Local row number */
6348     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6349   }
6350   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6351   PetscCall(PetscFree(jdxm));
6352   PetscFunctionReturn(PETSC_SUCCESS);
6353 }
6354 
6355 /*@
6356    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6357    of a set of rows and columns of a matrix.
6358 
6359    Collective
6360 
6361    Input Parameters:
6362 +  mat - the matrix
6363 .  numRows - the number of rows/columns to remove
6364 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6365 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6366 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6367 -  b - optional vector of right hand side, that will be adjusted by provided solution
6368 
6369    Level: intermediate
6370 
6371    Notes:
6372    See `MatZeroRowsColumns()` for details on how this routine operates.
6373 
6374    The grid coordinates are across the entire grid, not just the local portion
6375 
6376    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6377    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6378    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6379    `DM_BOUNDARY_PERIODIC` boundary type.
6380 
6381    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
6382    a single value per point) you can skip filling those indices.
6383 
6384    Fortran Note:
6385    `idxm` and `idxn` should be declared as
6386 $     MatStencil idxm(4, m)
6387    and the values inserted using
6388 .vb
6389     idxm(MatStencil_i, 1) = i
6390     idxm(MatStencil_j, 1) = j
6391     idxm(MatStencil_k, 1) = k
6392     idxm(MatStencil_c, 1) = c
6393     etc
6394 .ve
6395 
6396 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6397           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6398 @*/
6399 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6400 {
6401   PetscInt  dim    = mat->stencil.dim;
6402   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6403   PetscInt *dims   = mat->stencil.dims + 1;
6404   PetscInt *starts = mat->stencil.starts;
6405   PetscInt *dxm    = (PetscInt *)rows;
6406   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6407 
6408   PetscFunctionBegin;
6409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6410   PetscValidType(mat, 1);
6411   if (numRows) PetscValidPointer(rows, 3);
6412 
6413   PetscCall(PetscMalloc1(numRows, &jdxm));
6414   for (i = 0; i < numRows; ++i) {
6415     /* Skip unused dimensions (they are ordered k, j, i, c) */
6416     for (j = 0; j < 3 - sdim; ++j) dxm++;
6417     /* Local index in X dir */
6418     tmp = *dxm++ - starts[0];
6419     /* Loop over remaining dimensions */
6420     for (j = 0; j < dim - 1; ++j) {
6421       /* If nonlocal, set index to be negative */
6422       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6423       /* Update local index */
6424       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6425     }
6426     /* Skip component slot if necessary */
6427     if (mat->stencil.noc) dxm++;
6428     /* Local row number */
6429     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6430   }
6431   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6432   PetscCall(PetscFree(jdxm));
6433   PetscFunctionReturn(PETSC_SUCCESS);
6434 }
6435 
6436 /*@C
6437    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6438    of a set of rows of a matrix; using local numbering of rows.
6439 
6440    Collective
6441 
6442    Input Parameters:
6443 +  mat - the matrix
6444 .  numRows - the number of rows to remove
6445 .  rows - the local row indices
6446 .  diag - value put in all diagonals of eliminated rows
6447 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6448 -  b - optional vector of right hand side, that will be adjusted by provided solution
6449 
6450    Level: intermediate
6451 
6452    Notes:
6453    Before calling `MatZeroRowsLocal()`, the user must first set the
6454    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6455 
6456    See `MatZeroRows()` for details on how this routine operates.
6457 
6458 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6459           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6460 @*/
6461 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6462 {
6463   PetscFunctionBegin;
6464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6465   PetscValidType(mat, 1);
6466   if (numRows) PetscValidIntPointer(rows, 3);
6467   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6468   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6469   MatCheckPreallocated(mat, 1);
6470 
6471   if (mat->ops->zerorowslocal) {
6472     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6473   } else {
6474     IS              is, newis;
6475     const PetscInt *newRows;
6476 
6477     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6478     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6479     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6480     PetscCall(ISGetIndices(newis, &newRows));
6481     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6482     PetscCall(ISRestoreIndices(newis, &newRows));
6483     PetscCall(ISDestroy(&newis));
6484     PetscCall(ISDestroy(&is));
6485   }
6486   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6487   PetscFunctionReturn(PETSC_SUCCESS);
6488 }
6489 
6490 /*@
6491    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6492    of a set of rows of a matrix; using local numbering of rows.
6493 
6494    Collective
6495 
6496    Input Parameters:
6497 +  mat - the matrix
6498 .  is - index set of rows to remove
6499 .  diag - value put in all diagonals of eliminated rows
6500 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6501 -  b - optional vector of right hand side, that will be adjusted by provided solution
6502 
6503    Level: intermediate
6504 
6505    Notes:
6506    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6507    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6508 
6509    See `MatZeroRows()` for details on how this routine operates.
6510 
6511 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6512           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6513 @*/
6514 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6515 {
6516   PetscInt        numRows;
6517   const PetscInt *rows;
6518 
6519   PetscFunctionBegin;
6520   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6521   PetscValidType(mat, 1);
6522   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6523   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6524   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6525   MatCheckPreallocated(mat, 1);
6526 
6527   PetscCall(ISGetLocalSize(is, &numRows));
6528   PetscCall(ISGetIndices(is, &rows));
6529   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6530   PetscCall(ISRestoreIndices(is, &rows));
6531   PetscFunctionReturn(PETSC_SUCCESS);
6532 }
6533 
6534 /*@
6535    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6536    of a set of rows and columns of a matrix; using local numbering of rows.
6537 
6538    Collective
6539 
6540    Input Parameters:
6541 +  mat - the matrix
6542 .  numRows - the number of rows to remove
6543 .  rows - the global row indices
6544 .  diag - value put in all diagonals of eliminated rows
6545 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6546 -  b - optional vector of right hand side, that will be adjusted by provided solution
6547 
6548    Level: intermediate
6549 
6550    Notes:
6551    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6552    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6553 
6554    See `MatZeroRowsColumns()` for details on how this routine operates.
6555 
6556 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6557           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6558 @*/
6559 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6560 {
6561   IS              is, newis;
6562   const PetscInt *newRows;
6563 
6564   PetscFunctionBegin;
6565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6566   PetscValidType(mat, 1);
6567   if (numRows) PetscValidIntPointer(rows, 3);
6568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6570   MatCheckPreallocated(mat, 1);
6571 
6572   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6573   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6574   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6575   PetscCall(ISGetIndices(newis, &newRows));
6576   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6577   PetscCall(ISRestoreIndices(newis, &newRows));
6578   PetscCall(ISDestroy(&newis));
6579   PetscCall(ISDestroy(&is));
6580   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6581   PetscFunctionReturn(PETSC_SUCCESS);
6582 }
6583 
6584 /*@
6585    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6586    of a set of rows and columns of a matrix; using local numbering of rows.
6587 
6588    Collective
6589 
6590    Input Parameters:
6591 +  mat - the matrix
6592 .  is - index set of rows to remove
6593 .  diag - value put in all diagonals of eliminated rows
6594 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6595 -  b - optional vector of right hand side, that will be adjusted by provided solution
6596 
6597    Level: intermediate
6598 
6599    Notes:
6600    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6601    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6602 
6603    See `MatZeroRowsColumns()` for details on how this routine operates.
6604 
6605 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6606           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6607 @*/
6608 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6609 {
6610   PetscInt        numRows;
6611   const PetscInt *rows;
6612 
6613   PetscFunctionBegin;
6614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6615   PetscValidType(mat, 1);
6616   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6617   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6618   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6619   MatCheckPreallocated(mat, 1);
6620 
6621   PetscCall(ISGetLocalSize(is, &numRows));
6622   PetscCall(ISGetIndices(is, &rows));
6623   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6624   PetscCall(ISRestoreIndices(is, &rows));
6625   PetscFunctionReturn(PETSC_SUCCESS);
6626 }
6627 
6628 /*@C
6629    MatGetSize - Returns the numbers of rows and columns in a matrix.
6630 
6631    Not Collective
6632 
6633    Input Parameter:
6634 .  mat - the matrix
6635 
6636    Output Parameters:
6637 +  m - the number of global rows
6638 -  n - the number of global columns
6639 
6640    Level: beginner
6641 
6642    Note:
6643    Both output parameters can be `NULL` on input.
6644 
6645 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6646 @*/
6647 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6648 {
6649   PetscFunctionBegin;
6650   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6651   if (m) *m = mat->rmap->N;
6652   if (n) *n = mat->cmap->N;
6653   PetscFunctionReturn(PETSC_SUCCESS);
6654 }
6655 
6656 /*@C
6657    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6658    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6659 
6660    Not Collective
6661 
6662    Input Parameter:
6663 .  mat - the matrix
6664 
6665    Output Parameters:
6666 +  m - the number of local rows, use `NULL` to not obtain this value
6667 -  n - the number of local columns, use `NULL` to not obtain this value
6668 
6669    Level: beginner
6670 
6671 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6672 @*/
6673 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6674 {
6675   PetscFunctionBegin;
6676   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6677   if (m) PetscValidIntPointer(m, 2);
6678   if (n) PetscValidIntPointer(n, 3);
6679   if (m) *m = mat->rmap->n;
6680   if (n) *n = mat->cmap->n;
6681   PetscFunctionReturn(PETSC_SUCCESS);
6682 }
6683 
6684 /*@C
6685    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6686    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6687 
6688    Not Collective, unless matrix has not been allocated, then collective
6689 
6690    Input Parameter:
6691 .  mat - the matrix
6692 
6693    Output Parameters:
6694 +  m - the global index of the first local column, use `NULL` to not obtain this value
6695 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6696 
6697    Level: developer
6698 
6699 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6700 @*/
6701 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6702 {
6703   PetscFunctionBegin;
6704   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6705   PetscValidType(mat, 1);
6706   if (m) PetscValidIntPointer(m, 2);
6707   if (n) PetscValidIntPointer(n, 3);
6708   MatCheckPreallocated(mat, 1);
6709   if (m) *m = mat->cmap->rstart;
6710   if (n) *n = mat->cmap->rend;
6711   PetscFunctionReturn(PETSC_SUCCESS);
6712 }
6713 
6714 /*@C
6715    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6716    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
6717    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6718 
6719    Not Collective
6720 
6721    Input Parameter:
6722 .  mat - the matrix
6723 
6724    Output Parameters:
6725 +  m - the global index of the first local row, use `NULL` to not obtain this value
6726 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6727 
6728    Level: beginner
6729 
6730    Note:
6731   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6732   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6733   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6734 
6735 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6736           `PetscLayout`
6737 @*/
6738 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6739 {
6740   PetscFunctionBegin;
6741   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6742   PetscValidType(mat, 1);
6743   if (m) PetscValidIntPointer(m, 2);
6744   if (n) PetscValidIntPointer(n, 3);
6745   MatCheckPreallocated(mat, 1);
6746   if (m) *m = mat->rmap->rstart;
6747   if (n) *n = mat->rmap->rend;
6748   PetscFunctionReturn(PETSC_SUCCESS);
6749 }
6750 
6751 /*@C
6752    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6753    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
6754    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6755 
6756    Not Collective, unless matrix has not been allocated
6757 
6758    Input Parameter:
6759 .  mat - the matrix
6760 
6761    Output Parameter:
6762 .  ranges - start of each processors portion plus one more than the total length at the end
6763 
6764    Level: beginner
6765 
6766 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6767 @*/
6768 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6769 {
6770   PetscFunctionBegin;
6771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6772   PetscValidType(mat, 1);
6773   MatCheckPreallocated(mat, 1);
6774   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6775   PetscFunctionReturn(PETSC_SUCCESS);
6776 }
6777 
6778 /*@C
6779    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6780    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6781 
6782    Not Collective, unless matrix has not been allocated
6783 
6784    Input Parameter:
6785 .  mat - the matrix
6786 
6787    Output Parameter:
6788 .  ranges - start of each processors portion plus one more then the total length at the end
6789 
6790    Level: beginner
6791 
6792 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6793 @*/
6794 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6795 {
6796   PetscFunctionBegin;
6797   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6798   PetscValidType(mat, 1);
6799   MatCheckPreallocated(mat, 1);
6800   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6801   PetscFunctionReturn(PETSC_SUCCESS);
6802 }
6803 
6804 /*@C
6805    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6806    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6807    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6808 
6809    Not Collective
6810 
6811    Input Parameter:
6812 .  A - matrix
6813 
6814    Output Parameters:
6815 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6816 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6817 
6818    Level: intermediate
6819 
6820 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6821 @*/
6822 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6823 {
6824   PetscErrorCode (*f)(Mat, IS *, IS *);
6825 
6826   PetscFunctionBegin;
6827   MatCheckPreallocated(A, 1);
6828   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6829   if (f) {
6830     PetscCall((*f)(A, rows, cols));
6831   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6832     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6833     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6834   }
6835   PetscFunctionReturn(PETSC_SUCCESS);
6836 }
6837 
6838 /*@C
6839    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6840    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6841    to complete the factorization.
6842 
6843    Collective
6844 
6845    Input Parameters:
6846 +  fact - the factorized matrix obtained with `MatGetFactor()`
6847 .  mat - the matrix
6848 .  row - row permutation
6849 .  col - column permutation
6850 -  info - structure containing
6851 .vb
6852       levels - number of levels of fill.
6853       expected fill - as ratio of original fill.
6854       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6855                 missing diagonal entries)
6856 .ve
6857 
6858    Level: developer
6859 
6860    Notes:
6861    See [Matrix Factorization](sec_matfactor) for additional information.
6862 
6863    Most users should employ the `KSP` interface for linear solvers
6864    instead of working directly with matrix algebra routines such as this.
6865    See, e.g., `KSPCreate()`.
6866 
6867    Uses the definition of level of fill as in Y. Saad, 2003
6868 
6869    Developer Note:
6870    The Fortran interface is not autogenerated as the
6871    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6872 
6873    References:
6874 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6875 
6876 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6877           `MatGetOrdering()`, `MatFactorInfo`
6878 @*/
6879 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6880 {
6881   PetscFunctionBegin;
6882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6883   PetscValidType(mat, 2);
6884   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6885   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6886   PetscValidPointer(info, 5);
6887   PetscValidPointer(fact, 1);
6888   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6889   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6890   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6891   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6892   MatCheckPreallocated(mat, 2);
6893 
6894   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6895   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6896   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6897   PetscFunctionReturn(PETSC_SUCCESS);
6898 }
6899 
6900 /*@C
6901    MatICCFactorSymbolic - Performs symbolic incomplete
6902    Cholesky factorization for a symmetric matrix.  Use
6903    `MatCholeskyFactorNumeric()` to complete the factorization.
6904 
6905    Collective
6906 
6907    Input Parameters:
6908 +  fact - the factorized matrix obtained with `MatGetFactor()`
6909 .  mat - the matrix to be factored
6910 .  perm - row and column permutation
6911 -  info - structure containing
6912 .vb
6913       levels - number of levels of fill.
6914       expected fill - as ratio of original fill.
6915 .ve
6916 
6917    Level: developer
6918 
6919    Notes:
6920    Most users should employ the `KSP` interface for linear solvers
6921    instead of working directly with matrix algebra routines such as this.
6922    See, e.g., `KSPCreate()`.
6923 
6924    This uses the definition of level of fill as in Y. Saad, 2003
6925 
6926    Developer Note:
6927    The Fortran interface is not autogenerated as the
6928    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6929 
6930    References:
6931 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6932 
6933 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6934 @*/
6935 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6936 {
6937   PetscFunctionBegin;
6938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6939   PetscValidType(mat, 2);
6940   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6941   PetscValidPointer(info, 4);
6942   PetscValidPointer(fact, 1);
6943   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6944   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6945   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6946   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6947   MatCheckPreallocated(mat, 2);
6948 
6949   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6950   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6951   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6952   PetscFunctionReturn(PETSC_SUCCESS);
6953 }
6954 
6955 /*@C
6956    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6957    points to an array of valid matrices, they may be reused to store the new
6958    submatrices.
6959 
6960    Collective
6961 
6962    Input Parameters:
6963 +  mat - the matrix
6964 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6965 .  irow - index set of rows to extract
6966 .  icol - index set of columns to extract
6967 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6968 
6969    Output Parameter:
6970 .  submat - the array of submatrices
6971 
6972    Level: advanced
6973 
6974    Notes:
6975    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6976    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6977    to extract a parallel submatrix.
6978 
6979    Some matrix types place restrictions on the row and column
6980    indices, such as that they be sorted or that they be equal to each other.
6981 
6982    The index sets may not have duplicate entries.
6983 
6984    When extracting submatrices from a parallel matrix, each processor can
6985    form a different submatrix by setting the rows and columns of its
6986    individual index sets according to the local submatrix desired.
6987 
6988    When finished using the submatrices, the user should destroy
6989    them with `MatDestroySubMatrices()`.
6990 
6991    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6992    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6993 
6994    This routine creates the matrices in submat; you should NOT create them before
6995    calling it. It also allocates the array of matrix pointers submat.
6996 
6997    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6998    request one row/column in a block, they must request all rows/columns that are in
6999    that block. For example, if the block size is 2 you cannot request just row 0 and
7000    column 0.
7001 
7002    Fortran Note:
7003    The Fortran interface is slightly different from that given below; it
7004    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7005 
7006 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7007 @*/
7008 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7009 {
7010   PetscInt  i;
7011   PetscBool eq;
7012 
7013   PetscFunctionBegin;
7014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7015   PetscValidType(mat, 1);
7016   if (n) {
7017     PetscValidPointer(irow, 3);
7018     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7019     PetscValidPointer(icol, 4);
7020     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7021   }
7022   PetscValidPointer(submat, 6);
7023   if (n && scall == MAT_REUSE_MATRIX) {
7024     PetscValidPointer(*submat, 6);
7025     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7026   }
7027   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7028   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7029   MatCheckPreallocated(mat, 1);
7030   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7031   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7032   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7033   for (i = 0; i < n; i++) {
7034     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7035     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7036     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7037 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7038     if (mat->boundtocpu && mat->bindingpropagates) {
7039       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7040       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7041     }
7042 #endif
7043   }
7044   PetscFunctionReturn(PETSC_SUCCESS);
7045 }
7046 
7047 /*@C
7048    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7049 
7050    Collective
7051 
7052    Input Parameters:
7053 +  mat - the matrix
7054 .  n   - the number of submatrixes to be extracted
7055 .  irow - index set of rows to extract
7056 .  icol - index set of columns to extract
7057 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7058 
7059    Output Parameter:
7060 .  submat - the array of submatrices
7061 
7062    Level: advanced
7063 
7064    Note:
7065    This is used by `PCGASM`
7066 
7067 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7068 @*/
7069 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7070 {
7071   PetscInt  i;
7072   PetscBool eq;
7073 
7074   PetscFunctionBegin;
7075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7076   PetscValidType(mat, 1);
7077   if (n) {
7078     PetscValidPointer(irow, 3);
7079     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7080     PetscValidPointer(icol, 4);
7081     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7082   }
7083   PetscValidPointer(submat, 6);
7084   if (n && scall == MAT_REUSE_MATRIX) {
7085     PetscValidPointer(*submat, 6);
7086     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7087   }
7088   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7089   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7090   MatCheckPreallocated(mat, 1);
7091 
7092   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7093   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7094   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7095   for (i = 0; i < n; i++) {
7096     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7097     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7098   }
7099   PetscFunctionReturn(PETSC_SUCCESS);
7100 }
7101 
7102 /*@C
7103    MatDestroyMatrices - Destroys an array of matrices.
7104 
7105    Collective
7106 
7107    Input Parameters:
7108 +  n - the number of local matrices
7109 -  mat - the matrices (this is a pointer to the array of matrices)
7110 
7111    Level: advanced
7112 
7113     Note:
7114     Frees not only the matrices, but also the array that contains the matrices
7115 
7116     Fortran Note:
7117     This does not free the array.
7118 
7119 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7120 @*/
7121 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7122 {
7123   PetscInt i;
7124 
7125   PetscFunctionBegin;
7126   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7127   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7128   PetscValidPointer(mat, 2);
7129 
7130   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7131 
7132   /* memory is allocated even if n = 0 */
7133   PetscCall(PetscFree(*mat));
7134   PetscFunctionReturn(PETSC_SUCCESS);
7135 }
7136 
7137 /*@C
7138    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7139 
7140    Collective
7141 
7142    Input Parameters:
7143 +  n - the number of local matrices
7144 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7145                        sequence of `MatCreateSubMatrices()`)
7146 
7147    Level: advanced
7148 
7149     Note:
7150     Frees not only the matrices, but also the array that contains the matrices
7151 
7152     Fortran Note:
7153     This does not free the array.
7154 
7155 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7156 @*/
7157 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7158 {
7159   Mat mat0;
7160 
7161   PetscFunctionBegin;
7162   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7163   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7164   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7165   PetscValidPointer(mat, 2);
7166 
7167   mat0 = (*mat)[0];
7168   if (mat0 && mat0->ops->destroysubmatrices) {
7169     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7170   } else {
7171     PetscCall(MatDestroyMatrices(n, mat));
7172   }
7173   PetscFunctionReturn(PETSC_SUCCESS);
7174 }
7175 
7176 /*@C
7177    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7178 
7179    Collective
7180 
7181    Input Parameter:
7182 .  mat - the matrix
7183 
7184    Output Parameter:
7185 .  matstruct - the sequential matrix with the nonzero structure of mat
7186 
7187   Level: developer
7188 
7189 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7190 @*/
7191 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7192 {
7193   PetscFunctionBegin;
7194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7195   PetscValidPointer(matstruct, 2);
7196 
7197   PetscValidType(mat, 1);
7198   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7199   MatCheckPreallocated(mat, 1);
7200 
7201   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7202   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7203   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7204   PetscFunctionReturn(PETSC_SUCCESS);
7205 }
7206 
7207 /*@C
7208    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7209 
7210    Collective
7211 
7212    Input Parameter:
7213 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7214                        sequence of `MatGetSeqNonzeroStructure()`)
7215 
7216    Level: advanced
7217 
7218     Note:
7219     Frees not only the matrices, but also the array that contains the matrices
7220 
7221 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7222 @*/
7223 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7224 {
7225   PetscFunctionBegin;
7226   PetscValidPointer(mat, 1);
7227   PetscCall(MatDestroy(mat));
7228   PetscFunctionReturn(PETSC_SUCCESS);
7229 }
7230 
7231 /*@
7232    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7233    replaces the index sets by larger ones that represent submatrices with
7234    additional overlap.
7235 
7236    Collective
7237 
7238    Input Parameters:
7239 +  mat - the matrix
7240 .  n   - the number of index sets
7241 .  is  - the array of index sets (these index sets will changed during the call)
7242 -  ov  - the additional overlap requested
7243 
7244    Options Database Key:
7245 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7246 
7247    Level: developer
7248 
7249    Note:
7250    The computed overlap preserves the matrix block sizes when the blocks are square.
7251    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7252    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7253 
7254 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7255 @*/
7256 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7257 {
7258   PetscInt i, bs, cbs;
7259 
7260   PetscFunctionBegin;
7261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7262   PetscValidType(mat, 1);
7263   PetscValidLogicalCollectiveInt(mat, n, 2);
7264   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7265   if (n) {
7266     PetscValidPointer(is, 3);
7267     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7268   }
7269   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7270   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7271   MatCheckPreallocated(mat, 1);
7272 
7273   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7274   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7275   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7276   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7277   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7278   if (bs == cbs) {
7279     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7280   }
7281   PetscFunctionReturn(PETSC_SUCCESS);
7282 }
7283 
7284 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7285 
7286 /*@
7287    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7288    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7289    additional overlap.
7290 
7291    Collective
7292 
7293    Input Parameters:
7294 +  mat - the matrix
7295 .  n   - the number of index sets
7296 .  is  - the array of index sets (these index sets will changed during the call)
7297 -  ov  - the additional overlap requested
7298 
7299 `   Options Database Key:
7300 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7301 
7302    Level: developer
7303 
7304 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7305 @*/
7306 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7307 {
7308   PetscInt i;
7309 
7310   PetscFunctionBegin;
7311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7312   PetscValidType(mat, 1);
7313   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7314   if (n) {
7315     PetscValidPointer(is, 3);
7316     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7317   }
7318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7320   MatCheckPreallocated(mat, 1);
7321   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7322   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7323   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7324   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325   PetscFunctionReturn(PETSC_SUCCESS);
7326 }
7327 
7328 /*@
7329    MatGetBlockSize - Returns the matrix block size.
7330 
7331    Not Collective
7332 
7333    Input Parameter:
7334 .  mat - the matrix
7335 
7336    Output Parameter:
7337 .  bs - block size
7338 
7339    Level: intermediate
7340 
7341    Notes:
7342     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7343 
7344    If the block size has not been set yet this routine returns 1.
7345 
7346 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7347 @*/
7348 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7349 {
7350   PetscFunctionBegin;
7351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7352   PetscValidIntPointer(bs, 2);
7353   *bs = PetscAbs(mat->rmap->bs);
7354   PetscFunctionReturn(PETSC_SUCCESS);
7355 }
7356 
7357 /*@
7358    MatGetBlockSizes - Returns the matrix block row and column sizes.
7359 
7360    Not Collective
7361 
7362    Input Parameter:
7363 .  mat - the matrix
7364 
7365    Output Parameters:
7366 +  rbs - row block size
7367 -  cbs - column block size
7368 
7369    Level: intermediate
7370 
7371    Notes:
7372     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7373     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7374 
7375    If a block size has not been set yet this routine returns 1.
7376 
7377 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7378 @*/
7379 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7380 {
7381   PetscFunctionBegin;
7382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7383   if (rbs) PetscValidIntPointer(rbs, 2);
7384   if (cbs) PetscValidIntPointer(cbs, 3);
7385   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7386   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7387   PetscFunctionReturn(PETSC_SUCCESS);
7388 }
7389 
7390 /*@
7391    MatSetBlockSize - Sets the matrix block size.
7392 
7393    Logically Collective
7394 
7395    Input Parameters:
7396 +  mat - the matrix
7397 -  bs - block size
7398 
7399    Level: intermediate
7400 
7401    Notes:
7402     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7403     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7404 
7405     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7406     is compatible with the matrix local sizes.
7407 
7408 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7409 @*/
7410 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7411 {
7412   PetscFunctionBegin;
7413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7414   PetscValidLogicalCollectiveInt(mat, bs, 2);
7415   PetscCall(MatSetBlockSizes(mat, bs, bs));
7416   PetscFunctionReturn(PETSC_SUCCESS);
7417 }
7418 
7419 typedef struct {
7420   PetscInt         n;
7421   IS              *is;
7422   Mat             *mat;
7423   PetscObjectState nonzerostate;
7424   Mat              C;
7425 } EnvelopeData;
7426 
7427 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7428 {
7429   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7430   PetscCall(PetscFree(edata->is));
7431   PetscCall(PetscFree(edata));
7432   return PETSC_SUCCESS;
7433 }
7434 
7435 /*
7436    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7437          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7438 
7439    Collective
7440 
7441    Input Parameter:
7442 .  mat - the matrix
7443 
7444    Notes:
7445      There can be zeros within the blocks
7446 
7447      The blocks can overlap between processes, including laying on more than two processes
7448 
7449 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7450 */
7451 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7452 {
7453   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7454   PetscInt          *diag, *odiag, sc;
7455   VecScatter         scatter;
7456   PetscScalar       *seqv;
7457   const PetscScalar *parv;
7458   const PetscInt    *ia, *ja;
7459   PetscBool          set, flag, done;
7460   Mat                AA = mat, A;
7461   MPI_Comm           comm;
7462   PetscMPIInt        rank, size, tag;
7463   MPI_Status         status;
7464   PetscContainer     container;
7465   EnvelopeData      *edata;
7466   Vec                seq, par;
7467   IS                 isglobal;
7468 
7469   PetscFunctionBegin;
7470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7471   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7472   if (!set || !flag) {
7473     /* TOO: only needs nonzero structure of transpose */
7474     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7475     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7476   }
7477   PetscCall(MatAIJGetLocalMat(AA, &A));
7478   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7479   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7480 
7481   PetscCall(MatGetLocalSize(mat, &n, NULL));
7482   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7483   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7484   PetscCallMPI(MPI_Comm_size(comm, &size));
7485   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7486 
7487   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7488 
7489   if (rank > 0) {
7490     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7491     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7492   }
7493   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7494   for (i = 0; i < n; i++) {
7495     env = PetscMax(env, ja[ia[i + 1] - 1]);
7496     II  = rstart + i;
7497     if (env == II) {
7498       starts[lblocks]  = tbs;
7499       sizes[lblocks++] = 1 + II - tbs;
7500       tbs              = 1 + II;
7501     }
7502   }
7503   if (rank < size - 1) {
7504     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7505     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7506   }
7507 
7508   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7509   if (!set || !flag) PetscCall(MatDestroy(&AA));
7510   PetscCall(MatDestroy(&A));
7511 
7512   PetscCall(PetscNew(&edata));
7513   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7514   edata->n = lblocks;
7515   /* create IS needed for extracting blocks from the original matrix */
7516   PetscCall(PetscMalloc1(lblocks, &edata->is));
7517   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7518 
7519   /* Create the resulting inverse matrix structure with preallocation information */
7520   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7521   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7522   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7523   PetscCall(MatSetType(edata->C, MATAIJ));
7524 
7525   /* Communicate the start and end of each row, from each block to the correct rank */
7526   /* TODO: Use PetscSF instead of VecScatter */
7527   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7528   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7529   PetscCall(VecGetArrayWrite(seq, &seqv));
7530   for (PetscInt i = 0; i < lblocks; i++) {
7531     for (PetscInt j = 0; j < sizes[i]; j++) {
7532       seqv[cnt]     = starts[i];
7533       seqv[cnt + 1] = starts[i] + sizes[i];
7534       cnt += 2;
7535     }
7536   }
7537   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7538   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7539   sc -= cnt;
7540   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7541   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7542   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7543   PetscCall(ISDestroy(&isglobal));
7544   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7545   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7546   PetscCall(VecScatterDestroy(&scatter));
7547   PetscCall(VecDestroy(&seq));
7548   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7549   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7550   PetscCall(VecGetArrayRead(par, &parv));
7551   cnt = 0;
7552   PetscCall(MatGetSize(mat, NULL, &n));
7553   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7554     PetscInt start, end, d = 0, od = 0;
7555 
7556     start = (PetscInt)PetscRealPart(parv[cnt]);
7557     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7558     cnt += 2;
7559 
7560     if (start < cstart) {
7561       od += cstart - start + n - cend;
7562       d += cend - cstart;
7563     } else if (start < cend) {
7564       od += n - cend;
7565       d += cend - start;
7566     } else od += n - start;
7567     if (end <= cstart) {
7568       od -= cstart - end + n - cend;
7569       d -= cend - cstart;
7570     } else if (end < cend) {
7571       od -= n - cend;
7572       d -= cend - end;
7573     } else od -= n - end;
7574 
7575     odiag[i] = od;
7576     diag[i]  = d;
7577   }
7578   PetscCall(VecRestoreArrayRead(par, &parv));
7579   PetscCall(VecDestroy(&par));
7580   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7581   PetscCall(PetscFree2(diag, odiag));
7582   PetscCall(PetscFree2(sizes, starts));
7583 
7584   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7585   PetscCall(PetscContainerSetPointer(container, edata));
7586   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7587   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7588   PetscCall(PetscObjectDereference((PetscObject)container));
7589   PetscFunctionReturn(PETSC_SUCCESS);
7590 }
7591 
7592 /*@
7593   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7594 
7595   Collective
7596 
7597   Input Parameters:
7598 + A - the matrix
7599 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7600 
7601   Output Parameter:
7602 . C - matrix with inverted block diagonal of `A`
7603 
7604   Level: advanced
7605 
7606   Note:
7607      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7608 
7609 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7610 @*/
7611 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7612 {
7613   PetscContainer   container;
7614   EnvelopeData    *edata;
7615   PetscObjectState nonzerostate;
7616 
7617   PetscFunctionBegin;
7618   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7619   if (!container) {
7620     PetscCall(MatComputeVariableBlockEnvelope(A));
7621     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7622   }
7623   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7624   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7625   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7626   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7627 
7628   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7629   *C = edata->C;
7630 
7631   for (PetscInt i = 0; i < edata->n; i++) {
7632     Mat          D;
7633     PetscScalar *dvalues;
7634 
7635     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7636     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7637     PetscCall(MatSeqDenseInvert(D));
7638     PetscCall(MatDenseGetArray(D, &dvalues));
7639     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7640     PetscCall(MatDestroy(&D));
7641   }
7642   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7643   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7644   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7645   PetscFunctionReturn(PETSC_SUCCESS);
7646 }
7647 
7648 /*@
7649    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7650 
7651    Logically Collective
7652 
7653    Input Parameters:
7654 +  mat - the matrix
7655 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7656 -  bsizes - the block sizes
7657 
7658    Level: intermediate
7659 
7660    Notes:
7661     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7662 
7663     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.
7664 
7665 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7666           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7667 @*/
7668 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7669 {
7670   PetscInt i, ncnt = 0, nlocal;
7671 
7672   PetscFunctionBegin;
7673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7674   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7675   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7676   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7677   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);
7678   PetscCall(PetscFree(mat->bsizes));
7679   mat->nblocks = nblocks;
7680   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7681   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7682   PetscFunctionReturn(PETSC_SUCCESS);
7683 }
7684 
7685 /*@C
7686    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7687 
7688    Logically Collective; No Fortran Support
7689 
7690    Input Parameter:
7691 .  mat - the matrix
7692 
7693    Output Parameters:
7694 +  nblocks - the number of blocks on this process
7695 -  bsizes - the block sizes
7696 
7697    Level: intermediate
7698 
7699 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7700 @*/
7701 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7702 {
7703   PetscFunctionBegin;
7704   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7705   *nblocks = mat->nblocks;
7706   *bsizes  = mat->bsizes;
7707   PetscFunctionReturn(PETSC_SUCCESS);
7708 }
7709 
7710 /*@
7711    MatSetBlockSizes - Sets the matrix block row and column sizes.
7712 
7713    Logically Collective
7714 
7715    Input Parameters:
7716 +  mat - the matrix
7717 .  rbs - row block size
7718 -  cbs - column block size
7719 
7720    Level: intermediate
7721 
7722    Notes:
7723     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7724     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7725     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7726 
7727     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7728     are compatible with the matrix local sizes.
7729 
7730     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7731 
7732 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7733 @*/
7734 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7735 {
7736   PetscFunctionBegin;
7737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7738   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7739   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7740   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7741   if (mat->rmap->refcnt) {
7742     ISLocalToGlobalMapping l2g  = NULL;
7743     PetscLayout            nmap = NULL;
7744 
7745     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7746     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7747     PetscCall(PetscLayoutDestroy(&mat->rmap));
7748     mat->rmap          = nmap;
7749     mat->rmap->mapping = l2g;
7750   }
7751   if (mat->cmap->refcnt) {
7752     ISLocalToGlobalMapping l2g  = NULL;
7753     PetscLayout            nmap = NULL;
7754 
7755     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7756     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7757     PetscCall(PetscLayoutDestroy(&mat->cmap));
7758     mat->cmap          = nmap;
7759     mat->cmap->mapping = l2g;
7760   }
7761   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7762   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7763   PetscFunctionReturn(PETSC_SUCCESS);
7764 }
7765 
7766 /*@
7767    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7768 
7769    Logically Collective
7770 
7771    Input Parameters:
7772 +  mat - the matrix
7773 .  fromRow - matrix from which to copy row block size
7774 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7775 
7776    Level: developer
7777 
7778 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7779 @*/
7780 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7781 {
7782   PetscFunctionBegin;
7783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7784   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7785   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7786   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7787   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7788   PetscFunctionReturn(PETSC_SUCCESS);
7789 }
7790 
7791 /*@
7792    MatResidual - Default routine to calculate the residual r = b - Ax
7793 
7794    Collective
7795 
7796    Input Parameters:
7797 +  mat - the matrix
7798 .  b   - the right-hand-side
7799 -  x   - the approximate solution
7800 
7801    Output Parameter:
7802 .  r - location to store the residual
7803 
7804    Level: developer
7805 
7806 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7807 @*/
7808 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7809 {
7810   PetscFunctionBegin;
7811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7812   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7813   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7814   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7815   PetscValidType(mat, 1);
7816   MatCheckPreallocated(mat, 1);
7817   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7818   if (!mat->ops->residual) {
7819     PetscCall(MatMult(mat, x, r));
7820     PetscCall(VecAYPX(r, -1.0, b));
7821   } else {
7822     PetscUseTypeMethod(mat, residual, b, x, r);
7823   }
7824   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7825   PetscFunctionReturn(PETSC_SUCCESS);
7826 }
7827 
7828 /*MC
7829     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7830 
7831     Synopsis:
7832     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7833 
7834     Not Collective
7835 
7836     Input Parameters:
7837 +   A - the matrix
7838 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7839 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7840 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7841                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7842                  always used.
7843 
7844     Output Parameters:
7845 +   n - number of local rows in the (possibly compressed) matrix
7846 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7847 .   ja - the column indices
7848 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7849            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7850 
7851     Level: developer
7852 
7853     Note:
7854     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7855 
7856 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7857 M*/
7858 
7859 /*MC
7860     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7861 
7862     Synopsis:
7863     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7864 
7865     Not Collective
7866 
7867     Input Parameters:
7868 +   A - 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 .   n - number of local rows in the (possibly compressed) matrix
7875 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7876 .   ja - the column indices
7877 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7878            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7879 
7880     Level: developer
7881 
7882 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7883 M*/
7884 
7885 /*@C
7886     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7887 
7888    Collective
7889 
7890     Input Parameters:
7891 +   mat - the matrix
7892 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7893 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7894 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7895                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7896                  always used.
7897 
7898     Output Parameters:
7899 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7900 .   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
7901 .   ja - the column indices, use `NULL` if not needed
7902 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7903            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7904 
7905     Level: developer
7906 
7907     Notes:
7908     You CANNOT change any of the ia[] or ja[] values.
7909 
7910     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7911 
7912     Fortran Notes:
7913     Use
7914 .vb
7915     PetscInt, pointer :: ia(:),ja(:)
7916     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7917     ! Access the ith and jth entries via ia(i) and ja(j)
7918 .ve
7919    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7920 
7921 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7922 @*/
7923 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7924 {
7925   PetscFunctionBegin;
7926   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7927   PetscValidType(mat, 1);
7928   if (n) PetscValidIntPointer(n, 5);
7929   if (ia) PetscValidPointer(ia, 6);
7930   if (ja) PetscValidPointer(ja, 7);
7931   if (done) PetscValidBoolPointer(done, 8);
7932   MatCheckPreallocated(mat, 1);
7933   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7934   else {
7935     if (done) *done = PETSC_TRUE;
7936     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7937     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7938     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7939   }
7940   PetscFunctionReturn(PETSC_SUCCESS);
7941 }
7942 
7943 /*@C
7944     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7945 
7946     Collective
7947 
7948     Input Parameters:
7949 +   mat - the matrix
7950 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7951 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7952                 symmetrized
7953 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7954                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7955                  always used.
7956 .   n - number of columns in the (possibly compressed) matrix
7957 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7958 -   ja - the row indices
7959 
7960     Output Parameter:
7961 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7962 
7963     Level: developer
7964 
7965 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7966 @*/
7967 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7968 {
7969   PetscFunctionBegin;
7970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7971   PetscValidType(mat, 1);
7972   PetscValidIntPointer(n, 5);
7973   if (ia) PetscValidPointer(ia, 6);
7974   if (ja) PetscValidPointer(ja, 7);
7975   PetscValidBoolPointer(done, 8);
7976   MatCheckPreallocated(mat, 1);
7977   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7978   else {
7979     *done = PETSC_TRUE;
7980     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7981   }
7982   PetscFunctionReturn(PETSC_SUCCESS);
7983 }
7984 
7985 /*@C
7986     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7987 
7988     Collective
7989 
7990     Input Parameters:
7991 +   mat - the matrix
7992 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7993 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7994 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7995                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7996                  always used.
7997 .   n - size of (possibly compressed) matrix
7998 .   ia - the row pointers
7999 -   ja - the column indices
8000 
8001     Output Parameter:
8002 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8003 
8004     Level: developer
8005 
8006     Note:
8007     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8008     us of the array after it has been restored. If you pass `NULL`, it will
8009     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8010 
8011     Fortran Note:
8012    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8013 
8014 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8015 @*/
8016 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8017 {
8018   PetscFunctionBegin;
8019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8020   PetscValidType(mat, 1);
8021   if (ia) PetscValidPointer(ia, 6);
8022   if (ja) PetscValidPointer(ja, 7);
8023   if (done) PetscValidBoolPointer(done, 8);
8024   MatCheckPreallocated(mat, 1);
8025 
8026   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8027   else {
8028     if (done) *done = PETSC_TRUE;
8029     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8030     if (n) *n = 0;
8031     if (ia) *ia = NULL;
8032     if (ja) *ja = NULL;
8033   }
8034   PetscFunctionReturn(PETSC_SUCCESS);
8035 }
8036 
8037 /*@C
8038     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8039 
8040     Collective
8041 
8042     Input Parameters:
8043 +   mat - the matrix
8044 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8045 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8046 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8047                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8048                  always used.
8049 
8050     Output Parameters:
8051 +   n - size of (possibly compressed) matrix
8052 .   ia - the column pointers
8053 .   ja - the row indices
8054 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8055 
8056     Level: developer
8057 
8058 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8059 @*/
8060 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8061 {
8062   PetscFunctionBegin;
8063   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8064   PetscValidType(mat, 1);
8065   if (ia) PetscValidPointer(ia, 6);
8066   if (ja) PetscValidPointer(ja, 7);
8067   PetscValidBoolPointer(done, 8);
8068   MatCheckPreallocated(mat, 1);
8069 
8070   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8071   else {
8072     *done = PETSC_TRUE;
8073     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8074     if (n) *n = 0;
8075     if (ia) *ia = NULL;
8076     if (ja) *ja = NULL;
8077   }
8078   PetscFunctionReturn(PETSC_SUCCESS);
8079 }
8080 
8081 /*@C
8082     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8083 
8084     Collective
8085 
8086     Input Parameters:
8087 +   mat - the matrix
8088 .   ncolors - maximum color value
8089 .   n   - number of entries in colorarray
8090 -   colorarray - array indicating color for each column
8091 
8092     Output Parameter:
8093 .   iscoloring - coloring generated using colorarray information
8094 
8095     Level: developer
8096 
8097 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8098 @*/
8099 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8100 {
8101   PetscFunctionBegin;
8102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8103   PetscValidType(mat, 1);
8104   PetscValidIntPointer(colorarray, 4);
8105   PetscValidPointer(iscoloring, 5);
8106   MatCheckPreallocated(mat, 1);
8107 
8108   if (!mat->ops->coloringpatch) {
8109     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8110   } else {
8111     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8112   }
8113   PetscFunctionReturn(PETSC_SUCCESS);
8114 }
8115 
8116 /*@
8117    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8118 
8119    Logically Collective
8120 
8121    Input Parameter:
8122 .  mat - the factored matrix to be reset
8123 
8124    Level: developer
8125 
8126    Notes:
8127    This routine should be used only with factored matrices formed by in-place
8128    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8129    format).  This option can save memory, for example, when solving nonlinear
8130    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8131    ILU(0) preconditioner.
8132 
8133    One can specify in-place ILU(0) factorization by calling
8134 .vb
8135      PCType(pc,PCILU);
8136      PCFactorSeUseInPlace(pc);
8137 .ve
8138    or by using the options -pc_type ilu -pc_factor_in_place
8139 
8140    In-place factorization ILU(0) can also be used as a local
8141    solver for the blocks within the block Jacobi or additive Schwarz
8142    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8143    for details on setting local solver options.
8144 
8145    Most users should employ the `KSP` interface for linear solvers
8146    instead of working directly with matrix algebra routines such as this.
8147    See, e.g., `KSPCreate()`.
8148 
8149 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8150 @*/
8151 PetscErrorCode MatSetUnfactored(Mat mat)
8152 {
8153   PetscFunctionBegin;
8154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8155   PetscValidType(mat, 1);
8156   MatCheckPreallocated(mat, 1);
8157   mat->factortype = MAT_FACTOR_NONE;
8158   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8159   PetscUseTypeMethod(mat, setunfactored);
8160   PetscFunctionReturn(PETSC_SUCCESS);
8161 }
8162 
8163 /*MC
8164     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8165 
8166     Synopsis:
8167     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8168 
8169     Not Collective
8170 
8171     Input Parameter:
8172 .   x - matrix
8173 
8174     Output Parameters:
8175 +   xx_v - the Fortran pointer to the array
8176 -   ierr - error code
8177 
8178     Example of Usage:
8179 .vb
8180       PetscScalar, pointer xx_v(:,:)
8181       ....
8182       call MatDenseGetArrayF90(x,xx_v,ierr)
8183       a = xx_v(3)
8184       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8185 .ve
8186 
8187     Level: advanced
8188 
8189 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8190 M*/
8191 
8192 /*MC
8193     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8194     accessed with `MatDenseGetArrayF90()`.
8195 
8196     Synopsis:
8197     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8198 
8199     Not Collective
8200 
8201     Input Parameters:
8202 +   x - matrix
8203 -   xx_v - the Fortran90 pointer to the array
8204 
8205     Output Parameter:
8206 .   ierr - error code
8207 
8208     Example of Usage:
8209 .vb
8210        PetscScalar, pointer xx_v(:,:)
8211        ....
8212        call MatDenseGetArrayF90(x,xx_v,ierr)
8213        a = xx_v(3)
8214        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8215 .ve
8216 
8217     Level: advanced
8218 
8219 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8220 M*/
8221 
8222 /*MC
8223     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8224 
8225     Synopsis:
8226     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8227 
8228     Not Collective
8229 
8230     Input Parameter:
8231 .   x - matrix
8232 
8233     Output Parameters:
8234 +   xx_v - the Fortran pointer to the array
8235 -   ierr - error code
8236 
8237     Example of Usage:
8238 .vb
8239       PetscScalar, pointer xx_v(:)
8240       ....
8241       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8242       a = xx_v(3)
8243       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8244 .ve
8245 
8246     Level: advanced
8247 
8248 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8249 M*/
8250 
8251 /*MC
8252     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8253     accessed with `MatSeqAIJGetArrayF90()`.
8254 
8255     Synopsis:
8256     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8257 
8258     Not Collective
8259 
8260     Input Parameters:
8261 +   x - matrix
8262 -   xx_v - the Fortran90 pointer to the array
8263 
8264     Output Parameter:
8265 .   ierr - error code
8266 
8267     Example of Usage:
8268 .vb
8269        PetscScalar, pointer xx_v(:)
8270        ....
8271        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8272        a = xx_v(3)
8273        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8274 .ve
8275 
8276     Level: advanced
8277 
8278 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8279 M*/
8280 
8281 /*@
8282     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8283                       as the original matrix.
8284 
8285     Collective
8286 
8287     Input Parameters:
8288 +   mat - the original matrix
8289 .   isrow - parallel `IS` containing the rows this processor should obtain
8290 .   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.
8291 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8292 
8293     Output Parameter:
8294 .   newmat - the new submatrix, of the same type as the original matrix
8295 
8296     Level: advanced
8297 
8298     Notes:
8299     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8300 
8301     Some matrix types place restrictions on the row and column indices, such
8302     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;
8303     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8304 
8305     The index sets may not have duplicate entries.
8306 
8307       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8308    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8309    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8310    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8311    you are finished using it.
8312 
8313     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8314     the input matrix.
8315 
8316     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8317 
8318    Example usage:
8319    Consider the following 8x8 matrix with 34 non-zero values, that is
8320    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8321    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8322    as follows
8323 .vb
8324             1  2  0  |  0  3  0  |  0  4
8325     Proc0   0  5  6  |  7  0  0  |  8  0
8326             9  0 10  | 11  0  0  | 12  0
8327     -------------------------------------
8328            13  0 14  | 15 16 17  |  0  0
8329     Proc1   0 18  0  | 19 20 21  |  0  0
8330             0  0  0  | 22 23  0  | 24  0
8331     -------------------------------------
8332     Proc2  25 26 27  |  0  0 28  | 29  0
8333            30  0  0  | 31 32 33  |  0 34
8334 .ve
8335 
8336     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8337 
8338 .vb
8339             2  0  |  0  3  0  |  0
8340     Proc0   5  6  |  7  0  0  |  8
8341     -------------------------------
8342     Proc1  18  0  | 19 20 21  |  0
8343     -------------------------------
8344     Proc2  26 27  |  0  0 28  | 29
8345             0  0  | 31 32 33  |  0
8346 .ve
8347 
8348 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8349 @*/
8350 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8351 {
8352   PetscMPIInt size;
8353   Mat        *local;
8354   IS          iscoltmp;
8355   PetscBool   flg;
8356 
8357   PetscFunctionBegin;
8358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8359   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8360   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8361   PetscValidPointer(newmat, 5);
8362   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8363   PetscValidType(mat, 1);
8364   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8365   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8366 
8367   MatCheckPreallocated(mat, 1);
8368   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8369 
8370   if (!iscol || isrow == iscol) {
8371     PetscBool   stride;
8372     PetscMPIInt grabentirematrix = 0, grab;
8373     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8374     if (stride) {
8375       PetscInt first, step, n, rstart, rend;
8376       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8377       if (step == 1) {
8378         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8379         if (rstart == first) {
8380           PetscCall(ISGetLocalSize(isrow, &n));
8381           if (n == rend - rstart) grabentirematrix = 1;
8382         }
8383       }
8384     }
8385     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8386     if (grab) {
8387       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8388       if (cll == MAT_INITIAL_MATRIX) {
8389         *newmat = mat;
8390         PetscCall(PetscObjectReference((PetscObject)mat));
8391       }
8392       PetscFunctionReturn(PETSC_SUCCESS);
8393     }
8394   }
8395 
8396   if (!iscol) {
8397     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8398   } else {
8399     iscoltmp = iscol;
8400   }
8401 
8402   /* if original matrix is on just one processor then use submatrix generated */
8403   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8404     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8405     goto setproperties;
8406   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8407     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8408     *newmat = *local;
8409     PetscCall(PetscFree(local));
8410     goto setproperties;
8411   } else if (!mat->ops->createsubmatrix) {
8412     /* Create a new matrix type that implements the operation using the full matrix */
8413     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8414     switch (cll) {
8415     case MAT_INITIAL_MATRIX:
8416       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8417       break;
8418     case MAT_REUSE_MATRIX:
8419       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8420       break;
8421     default:
8422       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8423     }
8424     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8425     goto setproperties;
8426   }
8427 
8428   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8429   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8430   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8431 
8432 setproperties:
8433   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8434   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8435   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8436   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8437   PetscFunctionReturn(PETSC_SUCCESS);
8438 }
8439 
8440 /*@
8441    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8442 
8443    Not Collective
8444 
8445    Input Parameters:
8446 +  A - the matrix we wish to propagate options from
8447 -  B - the matrix we wish to propagate options to
8448 
8449    Level: beginner
8450 
8451    Note:
8452    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8453 
8454 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8455 @*/
8456 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8457 {
8458   PetscFunctionBegin;
8459   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8460   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8461   B->symmetry_eternal            = A->symmetry_eternal;
8462   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8463   B->symmetric                   = A->symmetric;
8464   B->structurally_symmetric      = A->structurally_symmetric;
8465   B->spd                         = A->spd;
8466   B->hermitian                   = A->hermitian;
8467   PetscFunctionReturn(PETSC_SUCCESS);
8468 }
8469 
8470 /*@
8471    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8472    used during the assembly process to store values that belong to
8473    other processors.
8474 
8475    Not Collective
8476 
8477    Input Parameters:
8478 +  mat   - the matrix
8479 .  size  - the initial size of the stash.
8480 -  bsize - the initial size of the block-stash(if used).
8481 
8482    Options Database Keys:
8483 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8484 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8485 
8486    Level: intermediate
8487 
8488    Notes:
8489      The block-stash is used for values set with `MatSetValuesBlocked()` while
8490      the stash is used for values set with `MatSetValues()`
8491 
8492      Run with the option -info and look for output of the form
8493      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8494      to determine the appropriate value, MM, to use for size and
8495      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8496      to determine the value, BMM to use for bsize
8497 
8498 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8499 @*/
8500 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8501 {
8502   PetscFunctionBegin;
8503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8504   PetscValidType(mat, 1);
8505   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8506   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8507   PetscFunctionReturn(PETSC_SUCCESS);
8508 }
8509 
8510 /*@
8511    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8512      the matrix
8513 
8514    Neighbor-wise Collective
8515 
8516    Input Parameters:
8517 +  mat   - the matrix
8518 .  x - the vector to be multiplied by the interpolation operator
8519 -  y - the vector to be added to the result
8520 
8521    Output Parameter:
8522 .  w - the resulting vector
8523 
8524    Level: intermediate
8525 
8526    Notes:
8527     `w` may be the same vector as `y`.
8528 
8529     This allows one to use either the restriction or interpolation (its transpose)
8530     matrix to do the interpolation
8531 
8532 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8533 @*/
8534 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8535 {
8536   PetscInt M, N, Ny;
8537 
8538   PetscFunctionBegin;
8539   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8540   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8541   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8542   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8543   PetscCall(MatGetSize(A, &M, &N));
8544   PetscCall(VecGetSize(y, &Ny));
8545   if (M == Ny) {
8546     PetscCall(MatMultAdd(A, x, y, w));
8547   } else {
8548     PetscCall(MatMultTransposeAdd(A, x, y, w));
8549   }
8550   PetscFunctionReturn(PETSC_SUCCESS);
8551 }
8552 
8553 /*@
8554    MatInterpolate - y = A*x or A'*x depending on the shape of
8555      the matrix
8556 
8557    Neighbor-wise Collective
8558 
8559    Input Parameters:
8560 +  mat   - the matrix
8561 -  x - the vector to be interpolated
8562 
8563    Output Parameter:
8564 .  y - the resulting vector
8565 
8566    Level: intermediate
8567 
8568    Note:
8569     This allows one to use either the restriction or interpolation (its transpose)
8570     matrix to do the interpolation
8571 
8572 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8573 @*/
8574 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8575 {
8576   PetscInt M, N, Ny;
8577 
8578   PetscFunctionBegin;
8579   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8580   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8581   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8582   PetscCall(MatGetSize(A, &M, &N));
8583   PetscCall(VecGetSize(y, &Ny));
8584   if (M == Ny) {
8585     PetscCall(MatMult(A, x, y));
8586   } else {
8587     PetscCall(MatMultTranspose(A, x, y));
8588   }
8589   PetscFunctionReturn(PETSC_SUCCESS);
8590 }
8591 
8592 /*@
8593    MatRestrict - y = A*x or A'*x
8594 
8595    Neighbor-wise Collective
8596 
8597    Input Parameters:
8598 +  mat   - the matrix
8599 -  x - the vector to be restricted
8600 
8601    Output Parameter:
8602 .  y - the resulting vector
8603 
8604    Level: intermediate
8605 
8606    Note:
8607     This allows one to use either the restriction or interpolation (its transpose)
8608     matrix to do the restriction
8609 
8610 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8611 @*/
8612 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8613 {
8614   PetscInt M, N, Ny;
8615 
8616   PetscFunctionBegin;
8617   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8618   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8619   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8620   PetscCall(MatGetSize(A, &M, &N));
8621   PetscCall(VecGetSize(y, &Ny));
8622   if (M == Ny) {
8623     PetscCall(MatMult(A, x, y));
8624   } else {
8625     PetscCall(MatMultTranspose(A, x, y));
8626   }
8627   PetscFunctionReturn(PETSC_SUCCESS);
8628 }
8629 
8630 /*@
8631    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8632 
8633    Neighbor-wise Collective
8634 
8635    Input Parameters:
8636 +  mat   - the matrix
8637 .  x - the input dense matrix to be multiplied
8638 -  w - the input dense matrix to be added to the result
8639 
8640    Output Parameter:
8641 .  y - the output dense matrix
8642 
8643    Level: intermediate
8644 
8645    Note:
8646     This allows one to use either the restriction or interpolation (its transpose)
8647     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8648     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8649 
8650 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8651 @*/
8652 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8653 {
8654   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8655   PetscBool trans = PETSC_TRUE;
8656   MatReuse  reuse = MAT_INITIAL_MATRIX;
8657 
8658   PetscFunctionBegin;
8659   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8660   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8661   PetscValidType(x, 2);
8662   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8663   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8664   PetscCall(MatGetSize(A, &M, &N));
8665   PetscCall(MatGetSize(x, &Mx, &Nx));
8666   if (N == Mx) trans = PETSC_FALSE;
8667   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);
8668   Mo = trans ? N : M;
8669   if (*y) {
8670     PetscCall(MatGetSize(*y, &My, &Ny));
8671     if (Mo == My && Nx == Ny) {
8672       reuse = MAT_REUSE_MATRIX;
8673     } else {
8674       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);
8675       PetscCall(MatDestroy(y));
8676     }
8677   }
8678 
8679   if (w && *y == w) { /* this is to minimize changes in PCMG */
8680     PetscBool flg;
8681 
8682     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8683     if (w) {
8684       PetscInt My, Ny, Mw, Nw;
8685 
8686       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8687       PetscCall(MatGetSize(*y, &My, &Ny));
8688       PetscCall(MatGetSize(w, &Mw, &Nw));
8689       if (!flg || My != Mw || Ny != Nw) w = NULL;
8690     }
8691     if (!w) {
8692       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8693       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8694       PetscCall(PetscObjectDereference((PetscObject)w));
8695     } else {
8696       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8697     }
8698   }
8699   if (!trans) {
8700     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8701   } else {
8702     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8703   }
8704   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8705   PetscFunctionReturn(PETSC_SUCCESS);
8706 }
8707 
8708 /*@
8709    MatMatInterpolate - Y = A*X or A'*X
8710 
8711    Neighbor-wise Collective
8712 
8713    Input Parameters:
8714 +  mat   - the matrix
8715 -  x - the input dense matrix
8716 
8717    Output Parameter:
8718 .  y - the output dense matrix
8719 
8720    Level: intermediate
8721 
8722    Note:
8723     This allows one to use either the restriction or interpolation (its transpose)
8724     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8725     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8726 
8727 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8728 @*/
8729 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8730 {
8731   PetscFunctionBegin;
8732   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8733   PetscFunctionReturn(PETSC_SUCCESS);
8734 }
8735 
8736 /*@
8737    MatMatRestrict - Y = A*X or A'*X
8738 
8739    Neighbor-wise Collective
8740 
8741    Input Parameters:
8742 +  mat   - the matrix
8743 -  x - the input dense matrix
8744 
8745    Output Parameter:
8746 .  y - the output dense matrix
8747 
8748    Level: intermediate
8749 
8750    Note:
8751     This allows one to use either the restriction or interpolation (its transpose)
8752     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8753     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8754 
8755 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8756 @*/
8757 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8758 {
8759   PetscFunctionBegin;
8760   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8761   PetscFunctionReturn(PETSC_SUCCESS);
8762 }
8763 
8764 /*@
8765    MatGetNullSpace - retrieves the null space of a matrix.
8766 
8767    Logically Collective
8768 
8769    Input Parameters:
8770 +  mat - the matrix
8771 -  nullsp - the null space object
8772 
8773    Level: developer
8774 
8775 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8776 @*/
8777 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8778 {
8779   PetscFunctionBegin;
8780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8781   PetscValidPointer(nullsp, 2);
8782   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8783   PetscFunctionReturn(PETSC_SUCCESS);
8784 }
8785 
8786 /*@
8787    MatSetNullSpace - attaches a null space to a matrix.
8788 
8789    Logically Collective
8790 
8791    Input Parameters:
8792 +  mat - the matrix
8793 -  nullsp - the null space object
8794 
8795    Level: advanced
8796 
8797    Notes:
8798       This null space is used by the `KSP` linear solvers to solve singular systems.
8799 
8800       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`
8801 
8802       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
8803       to zero but the linear system will still be solved in a least squares sense.
8804 
8805       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8806    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).
8807    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
8808    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
8809    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).
8810    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8811 
8812     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8813     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8814     routine also automatically calls `MatSetTransposeNullSpace()`.
8815 
8816     The user should call `MatNullSpaceDestroy()`.
8817 
8818 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8819           `KSPSetPCSide()`
8820 @*/
8821 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8822 {
8823   PetscFunctionBegin;
8824   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8825   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8826   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8827   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8828   mat->nullsp = nullsp;
8829   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8830   PetscFunctionReturn(PETSC_SUCCESS);
8831 }
8832 
8833 /*@
8834    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8835 
8836    Logically Collective
8837 
8838    Input Parameters:
8839 +  mat - the matrix
8840 -  nullsp - the null space object
8841 
8842    Level: developer
8843 
8844 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8845 @*/
8846 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8847 {
8848   PetscFunctionBegin;
8849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8850   PetscValidType(mat, 1);
8851   PetscValidPointer(nullsp, 2);
8852   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8853   PetscFunctionReturn(PETSC_SUCCESS);
8854 }
8855 
8856 /*@
8857    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8858 
8859    Logically Collective
8860 
8861    Input Parameters:
8862 +  mat - the matrix
8863 -  nullsp - the null space object
8864 
8865    Level: advanced
8866 
8867    Notes:
8868    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8869 
8870    See `MatSetNullSpace()`
8871 
8872 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8873 @*/
8874 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8875 {
8876   PetscFunctionBegin;
8877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8878   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8879   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8880   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8881   mat->transnullsp = nullsp;
8882   PetscFunctionReturn(PETSC_SUCCESS);
8883 }
8884 
8885 /*@
8886    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8887         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8888 
8889    Logically Collective
8890 
8891    Input Parameters:
8892 +  mat - the matrix
8893 -  nullsp - the null space object
8894 
8895    Level: advanced
8896 
8897    Notes:
8898    Overwrites any previous near null space that may have been attached
8899 
8900    You can remove the null space by calling this routine with an nullsp of `NULL`
8901 
8902 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8903 @*/
8904 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8905 {
8906   PetscFunctionBegin;
8907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8908   PetscValidType(mat, 1);
8909   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8910   MatCheckPreallocated(mat, 1);
8911   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8912   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8913   mat->nearnullsp = nullsp;
8914   PetscFunctionReturn(PETSC_SUCCESS);
8915 }
8916 
8917 /*@
8918    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8919 
8920    Not Collective
8921 
8922    Input Parameter:
8923 .  mat - the matrix
8924 
8925    Output Parameter:
8926 .  nullsp - the null space object, `NULL` if not set
8927 
8928    Level: advanced
8929 
8930 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8931 @*/
8932 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8933 {
8934   PetscFunctionBegin;
8935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8936   PetscValidType(mat, 1);
8937   PetscValidPointer(nullsp, 2);
8938   MatCheckPreallocated(mat, 1);
8939   *nullsp = mat->nearnullsp;
8940   PetscFunctionReturn(PETSC_SUCCESS);
8941 }
8942 
8943 /*@C
8944    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8945 
8946    Collective
8947 
8948    Input Parameters:
8949 +  mat - the matrix
8950 .  row - row/column permutation
8951 -  info - information on desired factorization process
8952 
8953    Level: developer
8954 
8955    Notes:
8956    Probably really in-place only when level of fill is zero, otherwise allocates
8957    new space to store factored matrix and deletes previous memory.
8958 
8959    Most users should employ the `KSP` interface for linear solvers
8960    instead of working directly with matrix algebra routines such as this.
8961    See, e.g., `KSPCreate()`.
8962 
8963    Developer Note:
8964    The Fortran interface is not autogenerated as the
8965    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8966 
8967 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8968 @*/
8969 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8970 {
8971   PetscFunctionBegin;
8972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8973   PetscValidType(mat, 1);
8974   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8975   PetscValidPointer(info, 3);
8976   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8977   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8978   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8979   MatCheckPreallocated(mat, 1);
8980   PetscUseTypeMethod(mat, iccfactor, row, info);
8981   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8982   PetscFunctionReturn(PETSC_SUCCESS);
8983 }
8984 
8985 /*@
8986    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8987          ghosted ones.
8988 
8989    Not Collective
8990 
8991    Input Parameters:
8992 +  mat - the matrix
8993 -  diag - the diagonal values, including ghost ones
8994 
8995    Level: developer
8996 
8997    Notes:
8998     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8999 
9000     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9001 
9002 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9003 @*/
9004 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9005 {
9006   PetscMPIInt size;
9007 
9008   PetscFunctionBegin;
9009   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9010   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9011   PetscValidType(mat, 1);
9012 
9013   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9014   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9015   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9016   if (size == 1) {
9017     PetscInt n, m;
9018     PetscCall(VecGetSize(diag, &n));
9019     PetscCall(MatGetSize(mat, NULL, &m));
9020     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9021     PetscCall(MatDiagonalScale(mat, NULL, diag));
9022   } else {
9023     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9024   }
9025   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9026   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9027   PetscFunctionReturn(PETSC_SUCCESS);
9028 }
9029 
9030 /*@
9031    MatGetInertia - Gets the inertia from a factored matrix
9032 
9033    Collective
9034 
9035    Input Parameter:
9036 .  mat - the matrix
9037 
9038    Output Parameters:
9039 +   nneg - number of negative eigenvalues
9040 .   nzero - number of zero eigenvalues
9041 -   npos - number of positive eigenvalues
9042 
9043    Level: advanced
9044 
9045    Note:
9046     Matrix must have been factored by `MatCholeskyFactor()`
9047 
9048 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9049 @*/
9050 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9051 {
9052   PetscFunctionBegin;
9053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9054   PetscValidType(mat, 1);
9055   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9056   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9057   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9058   PetscFunctionReturn(PETSC_SUCCESS);
9059 }
9060 
9061 /*@C
9062    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9063 
9064    Neighbor-wise Collective
9065 
9066    Input Parameters:
9067 +  mat - the factored matrix obtained with `MatGetFactor()`
9068 -  b - the right-hand-side vectors
9069 
9070    Output Parameter:
9071 .  x - the result vectors
9072 
9073    Level: developer
9074 
9075    Note:
9076    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9077    call `MatSolves`(A,x,x).
9078 
9079 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9080 @*/
9081 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9082 {
9083   PetscFunctionBegin;
9084   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9085   PetscValidType(mat, 1);
9086   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9087   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9088   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9089 
9090   MatCheckPreallocated(mat, 1);
9091   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9092   PetscUseTypeMethod(mat, solves, b, x);
9093   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9094   PetscFunctionReturn(PETSC_SUCCESS);
9095 }
9096 
9097 /*@
9098    MatIsSymmetric - Test whether a matrix is symmetric
9099 
9100    Collective
9101 
9102    Input Parameters:
9103 +  A - the matrix to test
9104 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9105 
9106    Output Parameter:
9107 .  flg - the result
9108 
9109    Level: intermediate
9110 
9111    Notes:
9112     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9113 
9114     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9115 
9116     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9117     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9118 
9119 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9120           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9121 @*/
9122 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9123 {
9124   PetscFunctionBegin;
9125   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9126   PetscValidBoolPointer(flg, 3);
9127 
9128   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9129   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9130   else {
9131     PetscUseTypeMethod(A, issymmetric, tol, flg);
9132     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9133   }
9134   PetscFunctionReturn(PETSC_SUCCESS);
9135 }
9136 
9137 /*@
9138    MatIsHermitian - Test whether a matrix is Hermitian
9139 
9140    Collective
9141 
9142    Input Parameters:
9143 +  A - the matrix to test
9144 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9145 
9146    Output Parameter:
9147 .  flg - the result
9148 
9149    Level: intermediate
9150 
9151    Notes:
9152     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9153 
9154     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9155 
9156     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9157     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9158 
9159 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9160           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9161 @*/
9162 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9163 {
9164   PetscFunctionBegin;
9165   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9166   PetscValidBoolPointer(flg, 3);
9167 
9168   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9169   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9170   else {
9171     PetscUseTypeMethod(A, ishermitian, tol, flg);
9172     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9173   }
9174   PetscFunctionReturn(PETSC_SUCCESS);
9175 }
9176 
9177 /*@
9178    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9179 
9180    Not Collective
9181 
9182    Input Parameter:
9183 .  A - the matrix to check
9184 
9185    Output Parameters:
9186 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9187 -  flg - the result (only valid if set is `PETSC_TRUE`)
9188 
9189    Level: advanced
9190 
9191    Notes:
9192    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9193    if you want it explicitly checked
9194 
9195     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9196     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9197 
9198 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9199 @*/
9200 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9201 {
9202   PetscFunctionBegin;
9203   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9204   PetscValidBoolPointer(set, 2);
9205   PetscValidBoolPointer(flg, 3);
9206   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9207     *set = PETSC_TRUE;
9208     *flg = PetscBool3ToBool(A->symmetric);
9209   } else {
9210     *set = PETSC_FALSE;
9211   }
9212   PetscFunctionReturn(PETSC_SUCCESS);
9213 }
9214 
9215 /*@
9216    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9217 
9218    Not Collective
9219 
9220    Input Parameter:
9221 .  A - the matrix to check
9222 
9223    Output Parameters:
9224 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9225 -  flg - the result (only valid if set is `PETSC_TRUE`)
9226 
9227    Level: advanced
9228 
9229    Notes:
9230    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9231 
9232    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9233    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9234 
9235 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9236 @*/
9237 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9238 {
9239   PetscFunctionBegin;
9240   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9241   PetscValidBoolPointer(set, 2);
9242   PetscValidBoolPointer(flg, 3);
9243   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9244     *set = PETSC_TRUE;
9245     *flg = PetscBool3ToBool(A->spd);
9246   } else {
9247     *set = PETSC_FALSE;
9248   }
9249   PetscFunctionReturn(PETSC_SUCCESS);
9250 }
9251 
9252 /*@
9253    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9254 
9255    Not Collective
9256 
9257    Input Parameter:
9258 .  A - the matrix to check
9259 
9260    Output Parameters:
9261 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9262 -  flg - the result (only valid if set is `PETSC_TRUE`)
9263 
9264    Level: advanced
9265 
9266    Notes:
9267    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9268    if you want it explicitly checked
9269 
9270    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9271    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9272 
9273 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9274 @*/
9275 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9276 {
9277   PetscFunctionBegin;
9278   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9279   PetscValidBoolPointer(set, 2);
9280   PetscValidBoolPointer(flg, 3);
9281   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9282     *set = PETSC_TRUE;
9283     *flg = PetscBool3ToBool(A->hermitian);
9284   } else {
9285     *set = PETSC_FALSE;
9286   }
9287   PetscFunctionReturn(PETSC_SUCCESS);
9288 }
9289 
9290 /*@
9291    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9292 
9293    Collective
9294 
9295    Input Parameter:
9296 .  A - the matrix to test
9297 
9298    Output Parameter:
9299 .  flg - the result
9300 
9301    Level: intermediate
9302 
9303    Notes:
9304    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9305 
9306    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
9307    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9308 
9309 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9310 @*/
9311 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9312 {
9313   PetscFunctionBegin;
9314   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9315   PetscValidBoolPointer(flg, 2);
9316   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9317     *flg = PetscBool3ToBool(A->structurally_symmetric);
9318   } else {
9319     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9320     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9321   }
9322   PetscFunctionReturn(PETSC_SUCCESS);
9323 }
9324 
9325 /*@
9326    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9327 
9328    Not Collective
9329 
9330    Input Parameter:
9331 .  A - the matrix to check
9332 
9333    Output Parameters:
9334 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9335 -  flg - the result (only valid if set is PETSC_TRUE)
9336 
9337    Level: advanced
9338 
9339    Notes:
9340    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
9341    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9342 
9343    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9344 
9345 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9346 @*/
9347 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9348 {
9349   PetscFunctionBegin;
9350   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9351   PetscValidBoolPointer(set, 2);
9352   PetscValidBoolPointer(flg, 3);
9353   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9354     *set = PETSC_TRUE;
9355     *flg = PetscBool3ToBool(A->structurally_symmetric);
9356   } else {
9357     *set = PETSC_FALSE;
9358   }
9359   PetscFunctionReturn(PETSC_SUCCESS);
9360 }
9361 
9362 /*@
9363    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9364        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9365 
9366     Not Collective
9367 
9368    Input Parameter:
9369 .   mat - the matrix
9370 
9371    Output Parameters:
9372 +   nstash   - the size of the stash
9373 .   reallocs - the number of additional mallocs incurred.
9374 .   bnstash   - the size of the block stash
9375 -   breallocs - the number of additional mallocs incurred.in the block stash
9376 
9377    Level: advanced
9378 
9379 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9380 @*/
9381 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9382 {
9383   PetscFunctionBegin;
9384   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9385   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9386   PetscFunctionReturn(PETSC_SUCCESS);
9387 }
9388 
9389 /*@C
9390    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9391    parallel layout, `PetscLayout` for rows and columns
9392 
9393    Collective
9394 
9395    Input Parameter:
9396 .  mat - the matrix
9397 
9398    Output Parameters:
9399 +   right - (optional) vector that the matrix can be multiplied against
9400 -   left - (optional) vector that the matrix vector product can be stored in
9401 
9402   Level: advanced
9403 
9404    Notes:
9405     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()`.
9406 
9407     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9408 
9409 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9410 @*/
9411 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9412 {
9413   PetscFunctionBegin;
9414   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9415   PetscValidType(mat, 1);
9416   if (mat->ops->getvecs) {
9417     PetscUseTypeMethod(mat, getvecs, right, left);
9418   } else {
9419     PetscInt rbs, cbs;
9420     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9421     if (right) {
9422       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9423       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9424       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9425       PetscCall(VecSetBlockSize(*right, cbs));
9426       PetscCall(VecSetType(*right, mat->defaultvectype));
9427 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9428       if (mat->boundtocpu && mat->bindingpropagates) {
9429         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9430         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9431       }
9432 #endif
9433       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9434     }
9435     if (left) {
9436       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9437       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9438       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9439       PetscCall(VecSetBlockSize(*left, rbs));
9440       PetscCall(VecSetType(*left, mat->defaultvectype));
9441 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9442       if (mat->boundtocpu && mat->bindingpropagates) {
9443         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9444         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9445       }
9446 #endif
9447       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9448     }
9449   }
9450   PetscFunctionReturn(PETSC_SUCCESS);
9451 }
9452 
9453 /*@C
9454    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9455      with default values.
9456 
9457    Not Collective
9458 
9459    Input Parameter:
9460 .    info - the `MatFactorInfo` data structure
9461 
9462    Level: developer
9463 
9464    Notes:
9465     The solvers are generally used through the `KSP` and `PC` objects, for example
9466           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9467 
9468     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9469 
9470    Developer Note:
9471    The Fortran interface is not autogenerated as the
9472    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9473 
9474 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9475 @*/
9476 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9477 {
9478   PetscFunctionBegin;
9479   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9480   PetscFunctionReturn(PETSC_SUCCESS);
9481 }
9482 
9483 /*@
9484    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9485 
9486    Collective
9487 
9488    Input Parameters:
9489 +  mat - the factored matrix
9490 -  is - the index set defining the Schur indices (0-based)
9491 
9492    Level: advanced
9493 
9494    Notes:
9495     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9496 
9497    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9498 
9499    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9500 
9501 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9502           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9503 @*/
9504 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9505 {
9506   PetscErrorCode (*f)(Mat, IS);
9507 
9508   PetscFunctionBegin;
9509   PetscValidType(mat, 1);
9510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9511   PetscValidType(is, 2);
9512   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9513   PetscCheckSameComm(mat, 1, is, 2);
9514   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9515   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9516   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9517   PetscCall(MatDestroy(&mat->schur));
9518   PetscCall((*f)(mat, is));
9519   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9520   PetscFunctionReturn(PETSC_SUCCESS);
9521 }
9522 
9523 /*@
9524   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9525 
9526    Logically Collective
9527 
9528    Input Parameters:
9529 +  F - the factored matrix obtained by calling `MatGetFactor()`
9530 .  S - location where to return the Schur complement, can be `NULL`
9531 -  status - the status of the Schur complement matrix, can be `NULL`
9532 
9533    Level: advanced
9534 
9535    Notes:
9536    You must call `MatFactorSetSchurIS()` before calling this routine.
9537 
9538    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9539 
9540    The routine provides a copy of the Schur matrix stored within the solver data structures.
9541    The caller must destroy the object when it is no longer needed.
9542    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9543 
9544    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)
9545 
9546    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9547 
9548    Developer Note:
9549     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9550    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9551 
9552 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9553 @*/
9554 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9555 {
9556   PetscFunctionBegin;
9557   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9558   if (S) PetscValidPointer(S, 2);
9559   if (status) PetscValidPointer(status, 3);
9560   if (S) {
9561     PetscErrorCode (*f)(Mat, Mat *);
9562 
9563     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9564     if (f) {
9565       PetscCall((*f)(F, S));
9566     } else {
9567       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9568     }
9569   }
9570   if (status) *status = F->schur_status;
9571   PetscFunctionReturn(PETSC_SUCCESS);
9572 }
9573 
9574 /*@
9575   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9576 
9577    Logically Collective
9578 
9579    Input Parameters:
9580 +  F - the factored matrix obtained by calling `MatGetFactor()`
9581 .  *S - location where to return the Schur complement, can be `NULL`
9582 -  status - the status of the Schur complement matrix, can be `NULL`
9583 
9584    Level: advanced
9585 
9586    Notes:
9587    You must call `MatFactorSetSchurIS()` before calling this routine.
9588 
9589    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9590 
9591    The routine returns a the Schur Complement stored within the data structures of the solver.
9592 
9593    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9594 
9595    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9596 
9597    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9598 
9599    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9600 
9601 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9602 @*/
9603 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9604 {
9605   PetscFunctionBegin;
9606   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9607   if (S) PetscValidPointer(S, 2);
9608   if (status) PetscValidPointer(status, 3);
9609   if (S) *S = F->schur;
9610   if (status) *status = F->schur_status;
9611   PetscFunctionReturn(PETSC_SUCCESS);
9612 }
9613 
9614 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9615 {
9616   Mat S = F->schur;
9617 
9618   PetscFunctionBegin;
9619   switch (F->schur_status) {
9620   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9621   case MAT_FACTOR_SCHUR_INVERTED:
9622     if (S) {
9623       S->ops->solve             = NULL;
9624       S->ops->matsolve          = NULL;
9625       S->ops->solvetranspose    = NULL;
9626       S->ops->matsolvetranspose = NULL;
9627       S->ops->solveadd          = NULL;
9628       S->ops->solvetransposeadd = NULL;
9629       S->factortype             = MAT_FACTOR_NONE;
9630       PetscCall(PetscFree(S->solvertype));
9631     }
9632   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9633     break;
9634   default:
9635     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9636   }
9637   PetscFunctionReturn(PETSC_SUCCESS);
9638 }
9639 
9640 /*@
9641   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9642 
9643    Logically Collective
9644 
9645    Input Parameters:
9646 +  F - the factored matrix obtained by calling `MatGetFactor()`
9647 .  *S - location where the Schur complement is stored
9648 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9649 
9650    Level: advanced
9651 
9652 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9653 @*/
9654 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9655 {
9656   PetscFunctionBegin;
9657   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9658   if (S) {
9659     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9660     *S = NULL;
9661   }
9662   F->schur_status = status;
9663   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9664   PetscFunctionReturn(PETSC_SUCCESS);
9665 }
9666 
9667 /*@
9668   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9669 
9670    Logically Collective
9671 
9672    Input Parameters:
9673 +  F - the factored matrix obtained by calling `MatGetFactor()`
9674 .  rhs - location where the right hand side of the Schur complement system is stored
9675 -  sol - location where the solution of the Schur complement system has to be returned
9676 
9677    Level: advanced
9678 
9679    Notes:
9680    The sizes of the vectors should match the size of the Schur complement
9681 
9682    Must be called after `MatFactorSetSchurIS()`
9683 
9684 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9685 @*/
9686 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9687 {
9688   PetscFunctionBegin;
9689   PetscValidType(F, 1);
9690   PetscValidType(rhs, 2);
9691   PetscValidType(sol, 3);
9692   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9693   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9694   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9695   PetscCheckSameComm(F, 1, rhs, 2);
9696   PetscCheckSameComm(F, 1, sol, 3);
9697   PetscCall(MatFactorFactorizeSchurComplement(F));
9698   switch (F->schur_status) {
9699   case MAT_FACTOR_SCHUR_FACTORED:
9700     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9701     break;
9702   case MAT_FACTOR_SCHUR_INVERTED:
9703     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9704     break;
9705   default:
9706     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9707   }
9708   PetscFunctionReturn(PETSC_SUCCESS);
9709 }
9710 
9711 /*@
9712   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9713 
9714    Logically Collective
9715 
9716    Input Parameters:
9717 +  F - the factored matrix obtained by calling `MatGetFactor()`
9718 .  rhs - location where the right hand side of the Schur complement system is stored
9719 -  sol - location where the solution of the Schur complement system has to be returned
9720 
9721    Level: advanced
9722 
9723    Notes:
9724    The sizes of the vectors should match the size of the Schur complement
9725 
9726    Must be called after `MatFactorSetSchurIS()`
9727 
9728 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9729 @*/
9730 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9731 {
9732   PetscFunctionBegin;
9733   PetscValidType(F, 1);
9734   PetscValidType(rhs, 2);
9735   PetscValidType(sol, 3);
9736   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9737   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9738   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9739   PetscCheckSameComm(F, 1, rhs, 2);
9740   PetscCheckSameComm(F, 1, sol, 3);
9741   PetscCall(MatFactorFactorizeSchurComplement(F));
9742   switch (F->schur_status) {
9743   case MAT_FACTOR_SCHUR_FACTORED:
9744     PetscCall(MatSolve(F->schur, rhs, sol));
9745     break;
9746   case MAT_FACTOR_SCHUR_INVERTED:
9747     PetscCall(MatMult(F->schur, rhs, sol));
9748     break;
9749   default:
9750     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9751   }
9752   PetscFunctionReturn(PETSC_SUCCESS);
9753 }
9754 
9755 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9756 #if PetscDefined(HAVE_CUDA)
9757 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9758 #endif
9759 
9760 /* Schur status updated in the interface */
9761 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9762 {
9763   Mat S = F->schur;
9764 
9765   PetscFunctionBegin;
9766   if (S) {
9767     PetscMPIInt size;
9768     PetscBool   isdense, isdensecuda;
9769 
9770     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9771     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9772     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9773     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9774     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9775     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9776     if (isdense) {
9777       PetscCall(MatSeqDenseInvertFactors_Private(S));
9778     } else if (isdensecuda) {
9779 #if defined(PETSC_HAVE_CUDA)
9780       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9781 #endif
9782     }
9783     // HIP??????????????
9784     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9785   }
9786   PetscFunctionReturn(PETSC_SUCCESS);
9787 }
9788 
9789 /*@
9790   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9791 
9792    Logically Collective
9793 
9794    Input Parameter:
9795 .  F - the factored matrix obtained by calling `MatGetFactor()`
9796 
9797    Level: advanced
9798 
9799    Notes:
9800     Must be called after `MatFactorSetSchurIS()`.
9801 
9802    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9803 
9804 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9805 @*/
9806 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9807 {
9808   PetscFunctionBegin;
9809   PetscValidType(F, 1);
9810   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9811   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9812   PetscCall(MatFactorFactorizeSchurComplement(F));
9813   PetscCall(MatFactorInvertSchurComplement_Private(F));
9814   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9815   PetscFunctionReturn(PETSC_SUCCESS);
9816 }
9817 
9818 /*@
9819   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9820 
9821    Logically Collective
9822 
9823    Input Parameter:
9824 .  F - the factored matrix obtained by calling `MatGetFactor()`
9825 
9826    Level: advanced
9827 
9828    Note:
9829     Must be called after `MatFactorSetSchurIS()`
9830 
9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9832 @*/
9833 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9834 {
9835   MatFactorInfo info;
9836 
9837   PetscFunctionBegin;
9838   PetscValidType(F, 1);
9839   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9840   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9841   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9842   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9843   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9844     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9845   } else {
9846     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9847   }
9848   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9849   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9850   PetscFunctionReturn(PETSC_SUCCESS);
9851 }
9852 
9853 /*@
9854    MatPtAP - Creates the matrix product C = P^T * A * P
9855 
9856    Neighbor-wise Collective
9857 
9858    Input Parameters:
9859 +  A - the matrix
9860 .  P - the projection matrix
9861 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9862 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9863           if the result is a dense matrix this is irrelevant
9864 
9865    Output Parameter:
9866 .  C - the product matrix
9867 
9868    Level: intermediate
9869 
9870    Notes:
9871    C will be created and must be destroyed by the user with `MatDestroy()`.
9872 
9873    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9874 
9875    Developer Note:
9876    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9877 
9878 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9879 @*/
9880 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9881 {
9882   PetscFunctionBegin;
9883   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9884   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9885 
9886   if (scall == MAT_INITIAL_MATRIX) {
9887     PetscCall(MatProductCreate(A, P, NULL, C));
9888     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9889     PetscCall(MatProductSetAlgorithm(*C, "default"));
9890     PetscCall(MatProductSetFill(*C, fill));
9891 
9892     (*C)->product->api_user = PETSC_TRUE;
9893     PetscCall(MatProductSetFromOptions(*C));
9894     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);
9895     PetscCall(MatProductSymbolic(*C));
9896   } else { /* scall == MAT_REUSE_MATRIX */
9897     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9898   }
9899 
9900   PetscCall(MatProductNumeric(*C));
9901   (*C)->symmetric = A->symmetric;
9902   (*C)->spd       = A->spd;
9903   PetscFunctionReturn(PETSC_SUCCESS);
9904 }
9905 
9906 /*@
9907    MatRARt - Creates the matrix product C = R * A * R^T
9908 
9909    Neighbor-wise Collective
9910 
9911    Input Parameters:
9912 +  A - the matrix
9913 .  R - the projection matrix
9914 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9915 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9916           if the result is a dense matrix this is irrelevant
9917 
9918    Output Parameter:
9919 .  C - the product matrix
9920 
9921    Level: intermediate
9922 
9923    Notes:
9924    C will be created and must be destroyed by the user with `MatDestroy()`.
9925 
9926    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9927 
9928    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9929    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9930    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9931    We recommend using MatPtAP().
9932 
9933 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9934 @*/
9935 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9936 {
9937   PetscFunctionBegin;
9938   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9939   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9940 
9941   if (scall == MAT_INITIAL_MATRIX) {
9942     PetscCall(MatProductCreate(A, R, NULL, C));
9943     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9944     PetscCall(MatProductSetAlgorithm(*C, "default"));
9945     PetscCall(MatProductSetFill(*C, fill));
9946 
9947     (*C)->product->api_user = PETSC_TRUE;
9948     PetscCall(MatProductSetFromOptions(*C));
9949     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);
9950     PetscCall(MatProductSymbolic(*C));
9951   } else { /* scall == MAT_REUSE_MATRIX */
9952     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9953   }
9954 
9955   PetscCall(MatProductNumeric(*C));
9956   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9957   PetscFunctionReturn(PETSC_SUCCESS);
9958 }
9959 
9960 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9961 {
9962   PetscFunctionBegin;
9963   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9964 
9965   if (scall == MAT_INITIAL_MATRIX) {
9966     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9967     PetscCall(MatProductCreate(A, B, NULL, C));
9968     PetscCall(MatProductSetType(*C, ptype));
9969     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9970     PetscCall(MatProductSetFill(*C, fill));
9971 
9972     (*C)->product->api_user = PETSC_TRUE;
9973     PetscCall(MatProductSetFromOptions(*C));
9974     PetscCall(MatProductSymbolic(*C));
9975   } else { /* scall == MAT_REUSE_MATRIX */
9976     Mat_Product *product = (*C)->product;
9977     PetscBool    isdense;
9978 
9979     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9980     if (isdense && product && product->type != ptype) {
9981       PetscCall(MatProductClear(*C));
9982       product = NULL;
9983     }
9984     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9985     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9986       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9987       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9988       product           = (*C)->product;
9989       product->fill     = fill;
9990       product->api_user = PETSC_TRUE;
9991       product->clear    = PETSC_TRUE;
9992 
9993       PetscCall(MatProductSetType(*C, ptype));
9994       PetscCall(MatProductSetFromOptions(*C));
9995       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);
9996       PetscCall(MatProductSymbolic(*C));
9997     } else { /* user may change input matrices A or B when REUSE */
9998       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9999     }
10000   }
10001   PetscCall(MatProductNumeric(*C));
10002   PetscFunctionReturn(PETSC_SUCCESS);
10003 }
10004 
10005 /*@
10006    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10007 
10008    Neighbor-wise Collective
10009 
10010    Input Parameters:
10011 +  A - the left matrix
10012 .  B - the right matrix
10013 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10014 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10015           if the result is a dense matrix this is irrelevant
10016 
10017    Output Parameter:
10018 .  C - the product matrix
10019 
10020    Notes:
10021    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10022 
10023    `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
10024    call to this function with `MAT_INITIAL_MATRIX`.
10025 
10026    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10027 
10028    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`,
10029    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10030 
10031    Example of Usage:
10032 .vb
10033      MatProductCreate(A,B,NULL,&C);
10034      MatProductSetType(C,MATPRODUCT_AB);
10035      MatProductSymbolic(C);
10036      MatProductNumeric(C); // compute C=A * B
10037      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10038      MatProductNumeric(C);
10039      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10040      MatProductNumeric(C);
10041 .ve
10042 
10043    Level: intermediate
10044 
10045 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10046 @*/
10047 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10048 {
10049   PetscFunctionBegin;
10050   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10051   PetscFunctionReturn(PETSC_SUCCESS);
10052 }
10053 
10054 /*@
10055    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10056 
10057    Neighbor-wise Collective
10058 
10059    Input Parameters:
10060 +  A - the left matrix
10061 .  B - the right matrix
10062 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10063 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10064 
10065    Output Parameter:
10066 .  C - the product matrix
10067 
10068    Level: intermediate
10069 
10070    Notes:
10071    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10072 
10073    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10074 
10075    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10076    actually needed.
10077 
10078    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10079    and for pairs of `MATMPIDENSE` matrices.
10080 
10081    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10082 
10083    Options Database Keys:
10084 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10085               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10086               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10087 
10088 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10089 @*/
10090 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10091 {
10092   PetscFunctionBegin;
10093   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10094   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10095   PetscFunctionReturn(PETSC_SUCCESS);
10096 }
10097 
10098 /*@
10099    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10100 
10101    Neighbor-wise Collective
10102 
10103    Input Parameters:
10104 +  A - the left matrix
10105 .  B - the right matrix
10106 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10107 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10108 
10109    Output Parameter:
10110 .  C - the product matrix
10111 
10112    Level: intermediate
10113 
10114    Notes:
10115    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10116 
10117    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10118 
10119    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10120 
10121    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10122    actually needed.
10123 
10124    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10125    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10126 
10127 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10128 @*/
10129 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10130 {
10131   PetscFunctionBegin;
10132   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10133   PetscFunctionReturn(PETSC_SUCCESS);
10134 }
10135 
10136 /*@
10137    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10138 
10139    Neighbor-wise Collective
10140 
10141    Input Parameters:
10142 +  A - the left matrix
10143 .  B - the middle matrix
10144 .  C - the right matrix
10145 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10146 -  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
10147           if the result is a dense matrix this is irrelevant
10148 
10149    Output Parameter:
10150 .  D - the product matrix
10151 
10152    Level: intermediate
10153 
10154    Notes:
10155    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10156 
10157    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10158 
10159    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10160 
10161    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10162    actually needed.
10163 
10164    If you have many matrices with the same non-zero structure to multiply, you
10165    should use `MAT_REUSE_MATRIX` in all calls but the first
10166 
10167 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10168 @*/
10169 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10170 {
10171   PetscFunctionBegin;
10172   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10173   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10174 
10175   if (scall == MAT_INITIAL_MATRIX) {
10176     PetscCall(MatProductCreate(A, B, C, D));
10177     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10178     PetscCall(MatProductSetAlgorithm(*D, "default"));
10179     PetscCall(MatProductSetFill(*D, fill));
10180 
10181     (*D)->product->api_user = PETSC_TRUE;
10182     PetscCall(MatProductSetFromOptions(*D));
10183     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,
10184                ((PetscObject)C)->type_name);
10185     PetscCall(MatProductSymbolic(*D));
10186   } else { /* user may change input matrices when REUSE */
10187     PetscCall(MatProductReplaceMats(A, B, C, *D));
10188   }
10189   PetscCall(MatProductNumeric(*D));
10190   PetscFunctionReturn(PETSC_SUCCESS);
10191 }
10192 
10193 /*@
10194    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10195 
10196    Collective
10197 
10198    Input Parameters:
10199 +  mat - the matrix
10200 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10201 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10202 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10203 
10204    Output Parameter:
10205 .  matredundant - redundant matrix
10206 
10207    Level: advanced
10208 
10209    Notes:
10210    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10211    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10212 
10213    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10214    calling it.
10215 
10216    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10217 
10218 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10219 @*/
10220 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10221 {
10222   MPI_Comm       comm;
10223   PetscMPIInt    size;
10224   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10225   Mat_Redundant *redund     = NULL;
10226   PetscSubcomm   psubcomm   = NULL;
10227   MPI_Comm       subcomm_in = subcomm;
10228   Mat           *matseq;
10229   IS             isrow, iscol;
10230   PetscBool      newsubcomm = PETSC_FALSE;
10231 
10232   PetscFunctionBegin;
10233   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10234   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10235     PetscValidPointer(*matredundant, 5);
10236     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10237   }
10238 
10239   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10240   if (size == 1 || nsubcomm == 1) {
10241     if (reuse == MAT_INITIAL_MATRIX) {
10242       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10243     } else {
10244       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");
10245       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10246     }
10247     PetscFunctionReturn(PETSC_SUCCESS);
10248   }
10249 
10250   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10251   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10252   MatCheckPreallocated(mat, 1);
10253 
10254   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10255   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10256     /* create psubcomm, then get subcomm */
10257     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10258     PetscCallMPI(MPI_Comm_size(comm, &size));
10259     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10260 
10261     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10262     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10263     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10264     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10265     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10266     newsubcomm = PETSC_TRUE;
10267     PetscCall(PetscSubcommDestroy(&psubcomm));
10268   }
10269 
10270   /* get isrow, iscol and a local sequential matrix matseq[0] */
10271   if (reuse == MAT_INITIAL_MATRIX) {
10272     mloc_sub = PETSC_DECIDE;
10273     nloc_sub = PETSC_DECIDE;
10274     if (bs < 1) {
10275       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10276       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10277     } else {
10278       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10279       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10280     }
10281     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10282     rstart = rend - mloc_sub;
10283     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10284     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10285   } else { /* reuse == MAT_REUSE_MATRIX */
10286     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");
10287     /* retrieve subcomm */
10288     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10289     redund = (*matredundant)->redundant;
10290     isrow  = redund->isrow;
10291     iscol  = redund->iscol;
10292     matseq = redund->matseq;
10293   }
10294   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10295 
10296   /* get matredundant over subcomm */
10297   if (reuse == MAT_INITIAL_MATRIX) {
10298     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10299 
10300     /* create a supporting struct and attach it to C for reuse */
10301     PetscCall(PetscNew(&redund));
10302     (*matredundant)->redundant = redund;
10303     redund->isrow              = isrow;
10304     redund->iscol              = iscol;
10305     redund->matseq             = matseq;
10306     if (newsubcomm) {
10307       redund->subcomm = subcomm;
10308     } else {
10309       redund->subcomm = MPI_COMM_NULL;
10310     }
10311   } else {
10312     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10313   }
10314 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10315   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10316     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10317     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10318   }
10319 #endif
10320   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10321   PetscFunctionReturn(PETSC_SUCCESS);
10322 }
10323 
10324 /*@C
10325    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10326    a given `Mat`. Each submatrix can span multiple procs.
10327 
10328    Collective
10329 
10330    Input Parameters:
10331 +  mat - the matrix
10332 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10333 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10334 
10335    Output Parameter:
10336 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10337 
10338   Level: advanced
10339 
10340   Notes:
10341   The submatrix partition across processors is dictated by `subComm` a
10342   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10343   is not restricted to be grouped with consecutive original ranks.
10344 
10345   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10346   map directly to the layout of the original matrix [wrt the local
10347   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10348   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10349   the `subMat`. However the offDiagMat looses some columns - and this is
10350   reconstructed with `MatSetValues()`
10351 
10352   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10353 
10354 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10355 @*/
10356 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10357 {
10358   PetscMPIInt commsize, subCommSize;
10359 
10360   PetscFunctionBegin;
10361   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10362   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10363   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10364 
10365   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");
10366   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10367   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10368   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10369   PetscFunctionReturn(PETSC_SUCCESS);
10370 }
10371 
10372 /*@
10373    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10374 
10375    Not Collective
10376 
10377    Input Parameters:
10378 +  mat - matrix to extract local submatrix from
10379 .  isrow - local row indices for submatrix
10380 -  iscol - local column indices for submatrix
10381 
10382    Output Parameter:
10383 .  submat - the submatrix
10384 
10385    Level: intermediate
10386 
10387    Notes:
10388    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10389 
10390    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10391    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10392 
10393    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10394    `MatSetValuesBlockedLocal()` will also be implemented.
10395 
10396    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10397    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10398 
10399 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10400 @*/
10401 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10402 {
10403   PetscFunctionBegin;
10404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10405   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10406   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10407   PetscCheckSameComm(isrow, 2, iscol, 3);
10408   PetscValidPointer(submat, 4);
10409   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10410 
10411   if (mat->ops->getlocalsubmatrix) {
10412     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10413   } else {
10414     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10415   }
10416   PetscFunctionReturn(PETSC_SUCCESS);
10417 }
10418 
10419 /*@
10420    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10421 
10422    Not Collective
10423 
10424    Input Parameters:
10425 +  mat - matrix to extract local submatrix from
10426 .  isrow - local row indices for submatrix
10427 .  iscol - local column indices for submatrix
10428 -  submat - the submatrix
10429 
10430    Level: intermediate
10431 
10432 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10433 @*/
10434 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10435 {
10436   PetscFunctionBegin;
10437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10438   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10439   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10440   PetscCheckSameComm(isrow, 2, iscol, 3);
10441   PetscValidPointer(submat, 4);
10442   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10443 
10444   if (mat->ops->restorelocalsubmatrix) {
10445     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10446   } else {
10447     PetscCall(MatDestroy(submat));
10448   }
10449   *submat = NULL;
10450   PetscFunctionReturn(PETSC_SUCCESS);
10451 }
10452 
10453 /*@
10454    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10455 
10456    Collective
10457 
10458    Input Parameter:
10459 .  mat - the matrix
10460 
10461    Output Parameter:
10462 .  is - if any rows have zero diagonals this contains the list of them
10463 
10464    Level: developer
10465 
10466 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10467 @*/
10468 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10469 {
10470   PetscFunctionBegin;
10471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10472   PetscValidType(mat, 1);
10473   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10474   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10475 
10476   if (!mat->ops->findzerodiagonals) {
10477     Vec                diag;
10478     const PetscScalar *a;
10479     PetscInt          *rows;
10480     PetscInt           rStart, rEnd, r, nrow = 0;
10481 
10482     PetscCall(MatCreateVecs(mat, &diag, NULL));
10483     PetscCall(MatGetDiagonal(mat, diag));
10484     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10485     PetscCall(VecGetArrayRead(diag, &a));
10486     for (r = 0; r < rEnd - rStart; ++r)
10487       if (a[r] == 0.0) ++nrow;
10488     PetscCall(PetscMalloc1(nrow, &rows));
10489     nrow = 0;
10490     for (r = 0; r < rEnd - rStart; ++r)
10491       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10492     PetscCall(VecRestoreArrayRead(diag, &a));
10493     PetscCall(VecDestroy(&diag));
10494     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10495   } else {
10496     PetscUseTypeMethod(mat, findzerodiagonals, is);
10497   }
10498   PetscFunctionReturn(PETSC_SUCCESS);
10499 }
10500 
10501 /*@
10502    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10503 
10504    Collective
10505 
10506    Input Parameter:
10507 .  mat - the matrix
10508 
10509    Output Parameter:
10510 .  is - contains the list of rows with off block diagonal entries
10511 
10512    Level: developer
10513 
10514 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10515 @*/
10516 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10517 {
10518   PetscFunctionBegin;
10519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10520   PetscValidType(mat, 1);
10521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10523 
10524   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10525   PetscFunctionReturn(PETSC_SUCCESS);
10526 }
10527 
10528 /*@C
10529   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10530 
10531   Collective; No Fortran Support
10532 
10533   Input Parameter:
10534 . mat - the matrix
10535 
10536   Output Parameter:
10537 . values - the block inverses in column major order (FORTRAN-like)
10538 
10539   Level: advanced
10540 
10541    Notes:
10542    The size of the blocks is determined by the block size of the matrix.
10543 
10544    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10545 
10546    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10547 
10548 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10549 @*/
10550 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10551 {
10552   PetscFunctionBegin;
10553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10554   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10555   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10556   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10557   PetscFunctionReturn(PETSC_SUCCESS);
10558 }
10559 
10560 /*@C
10561   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10562 
10563   Collective; No Fortran Support
10564 
10565   Input Parameters:
10566 + mat - the matrix
10567 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10568 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10569 
10570   Output Parameter:
10571 . values - the block inverses in column major order (FORTRAN-like)
10572 
10573   Level: advanced
10574 
10575   Notes:
10576   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10577 
10578   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10579 
10580 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10581 @*/
10582 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10583 {
10584   PetscFunctionBegin;
10585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10586   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10587   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10588   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10589   PetscFunctionReturn(PETSC_SUCCESS);
10590 }
10591 
10592 /*@
10593   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10594 
10595   Collective
10596 
10597   Input Parameters:
10598 + A - the matrix
10599 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10600 
10601   Level: advanced
10602 
10603   Note:
10604   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10605 
10606 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10607 @*/
10608 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10609 {
10610   const PetscScalar *vals;
10611   PetscInt          *dnnz;
10612   PetscInt           m, rstart, rend, bs, i, j;
10613 
10614   PetscFunctionBegin;
10615   PetscCall(MatInvertBlockDiagonal(A, &vals));
10616   PetscCall(MatGetBlockSize(A, &bs));
10617   PetscCall(MatGetLocalSize(A, &m, NULL));
10618   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10619   PetscCall(PetscMalloc1(m / bs, &dnnz));
10620   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10621   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10622   PetscCall(PetscFree(dnnz));
10623   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10624   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10625   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10626   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10627   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10628   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10629   PetscFunctionReturn(PETSC_SUCCESS);
10630 }
10631 
10632 /*@C
10633     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10634     via `MatTransposeColoringCreate()`.
10635 
10636     Collective
10637 
10638     Input Parameter:
10639 .   c - coloring context
10640 
10641     Level: intermediate
10642 
10643 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10644 @*/
10645 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10646 {
10647   MatTransposeColoring matcolor = *c;
10648 
10649   PetscFunctionBegin;
10650   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10651   if (--((PetscObject)matcolor)->refct > 0) {
10652     matcolor = NULL;
10653     PetscFunctionReturn(PETSC_SUCCESS);
10654   }
10655 
10656   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10657   PetscCall(PetscFree(matcolor->rows));
10658   PetscCall(PetscFree(matcolor->den2sp));
10659   PetscCall(PetscFree(matcolor->colorforcol));
10660   PetscCall(PetscFree(matcolor->columns));
10661   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10662   PetscCall(PetscHeaderDestroy(c));
10663   PetscFunctionReturn(PETSC_SUCCESS);
10664 }
10665 
10666 /*@C
10667     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10668     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10669     `MatTransposeColoring` to sparse B.
10670 
10671     Collective
10672 
10673     Input Parameters:
10674 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10675 -   B - sparse matrix
10676 
10677     Output Parameter:
10678 .   Btdense - dense matrix B^T
10679 
10680     Level: developer
10681 
10682     Note:
10683     These are used internally for some implementations of `MatRARt()`
10684 
10685 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10686 @*/
10687 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10688 {
10689   PetscFunctionBegin;
10690   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10691   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10692   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10693 
10694   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10695   PetscFunctionReturn(PETSC_SUCCESS);
10696 }
10697 
10698 /*@C
10699     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10700     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10701     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10702     `Csp` from `Cden`.
10703 
10704     Collective
10705 
10706     Input Parameters:
10707 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10708 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10709 
10710     Output Parameter:
10711 .   Csp - sparse matrix
10712 
10713     Level: developer
10714 
10715     Note:
10716     These are used internally for some implementations of `MatRARt()`
10717 
10718 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10719 @*/
10720 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10721 {
10722   PetscFunctionBegin;
10723   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10724   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10725   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10726 
10727   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10728   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10729   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10730   PetscFunctionReturn(PETSC_SUCCESS);
10731 }
10732 
10733 /*@C
10734    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10735 
10736    Collective
10737 
10738    Input Parameters:
10739 +  mat - the matrix product C
10740 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10741 
10742     Output Parameter:
10743 .   color - the new coloring context
10744 
10745     Level: intermediate
10746 
10747 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10748           `MatTransColoringApplyDenToSp()`
10749 @*/
10750 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10751 {
10752   MatTransposeColoring c;
10753   MPI_Comm             comm;
10754 
10755   PetscFunctionBegin;
10756   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10757   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10758   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10759 
10760   c->ctype = iscoloring->ctype;
10761   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10762 
10763   *color = c;
10764   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10765   PetscFunctionReturn(PETSC_SUCCESS);
10766 }
10767 
10768 /*@
10769       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10770         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10771         same, otherwise it will be larger
10772 
10773      Not Collective
10774 
10775   Input Parameter:
10776 .    A  - the matrix
10777 
10778   Output Parameter:
10779 .    state - the current state
10780 
10781   Level: intermediate
10782 
10783   Notes:
10784     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10785          different matrices
10786 
10787     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10788 
10789     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10790 
10791 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10792 @*/
10793 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10794 {
10795   PetscFunctionBegin;
10796   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10797   *state = mat->nonzerostate;
10798   PetscFunctionReturn(PETSC_SUCCESS);
10799 }
10800 
10801 /*@
10802       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10803                  matrices from each processor
10804 
10805     Collective
10806 
10807    Input Parameters:
10808 +    comm - the communicators the parallel matrix will live on
10809 .    seqmat - the input sequential matrices
10810 .    n - number of local columns (or `PETSC_DECIDE`)
10811 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10812 
10813    Output Parameter:
10814 .    mpimat - the parallel matrix generated
10815 
10816     Level: developer
10817 
10818    Note:
10819     The number of columns of the matrix in EACH processor MUST be the same.
10820 
10821 .seealso: [](ch_matrices), `Mat`
10822 @*/
10823 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10824 {
10825   PetscMPIInt size;
10826 
10827   PetscFunctionBegin;
10828   PetscCallMPI(MPI_Comm_size(comm, &size));
10829   if (size == 1) {
10830     if (reuse == MAT_INITIAL_MATRIX) {
10831       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10832     } else {
10833       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10834     }
10835     PetscFunctionReturn(PETSC_SUCCESS);
10836   }
10837 
10838   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");
10839 
10840   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10841   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10842   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10843   PetscFunctionReturn(PETSC_SUCCESS);
10844 }
10845 
10846 /*@
10847      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10848 
10849     Collective
10850 
10851    Input Parameters:
10852 +    A   - the matrix to create subdomains from
10853 -    N   - requested number of subdomains
10854 
10855    Output Parameters:
10856 +    n   - number of subdomains resulting on this rank
10857 -    iss - `IS` list with indices of subdomains on this rank
10858 
10859     Level: advanced
10860 
10861     Note:
10862     The number of subdomains must be smaller than the communicator size
10863 
10864 .seealso: [](ch_matrices), `Mat`, `IS`
10865 @*/
10866 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10867 {
10868   MPI_Comm    comm, subcomm;
10869   PetscMPIInt size, rank, color;
10870   PetscInt    rstart, rend, k;
10871 
10872   PetscFunctionBegin;
10873   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10874   PetscCallMPI(MPI_Comm_size(comm, &size));
10875   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10876   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);
10877   *n    = 1;
10878   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10879   color = rank / k;
10880   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10881   PetscCall(PetscMalloc1(1, iss));
10882   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10883   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10884   PetscCallMPI(MPI_Comm_free(&subcomm));
10885   PetscFunctionReturn(PETSC_SUCCESS);
10886 }
10887 
10888 /*@
10889    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10890 
10891    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10892    If they are not the same, uses `MatMatMatMult()`.
10893 
10894    Once the coarse grid problem is constructed, correct for interpolation operators
10895    that are not of full rank, which can legitimately happen in the case of non-nested
10896    geometric multigrid.
10897 
10898    Input Parameters:
10899 +  restrct - restriction operator
10900 .  dA - fine grid matrix
10901 .  interpolate - interpolation operator
10902 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10903 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10904 
10905    Output Parameter:
10906 .  A - the Galerkin coarse matrix
10907 
10908    Options Database Key:
10909 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10910 
10911    Level: developer
10912 
10913 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10914 @*/
10915 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10916 {
10917   IS  zerorows;
10918   Vec diag;
10919 
10920   PetscFunctionBegin;
10921   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10922   /* Construct the coarse grid matrix */
10923   if (interpolate == restrct) {
10924     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10925   } else {
10926     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10927   }
10928 
10929   /* If the interpolation matrix is not of full rank, A will have zero rows.
10930      This can legitimately happen in the case of non-nested geometric multigrid.
10931      In that event, we set the rows of the matrix to the rows of the identity,
10932      ignoring the equations (as the RHS will also be zero). */
10933 
10934   PetscCall(MatFindZeroRows(*A, &zerorows));
10935 
10936   if (zerorows != NULL) { /* if there are any zero rows */
10937     PetscCall(MatCreateVecs(*A, &diag, NULL));
10938     PetscCall(MatGetDiagonal(*A, diag));
10939     PetscCall(VecISSet(diag, zerorows, 1.0));
10940     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10941     PetscCall(VecDestroy(&diag));
10942     PetscCall(ISDestroy(&zerorows));
10943   }
10944   PetscFunctionReturn(PETSC_SUCCESS);
10945 }
10946 
10947 /*@C
10948     MatSetOperation - Allows user to set a matrix operation for any matrix type
10949 
10950    Logically Collective
10951 
10952     Input Parameters:
10953 +   mat - the matrix
10954 .   op - the name of the operation
10955 -   f - the function that provides the operation
10956 
10957    Level: developer
10958 
10959     Usage:
10960 .vb
10961   extern PetscErrorCode usermult(Mat, Vec, Vec);
10962 
10963   PetscCall(MatCreateXXX(comm, ..., &A));
10964   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10965 .ve
10966 
10967     Notes:
10968     See the file `include/petscmat.h` for a complete list of matrix
10969     operations, which all have the form MATOP_<OPERATION>, where
10970     <OPERATION> is the name (in all capital letters) of the
10971     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10972 
10973     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10974     sequence as the usual matrix interface routines, since they
10975     are intended to be accessed via the usual matrix interface
10976     routines, e.g.,
10977 .vb
10978   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10979 .ve
10980 
10981     In particular each function MUST return `PETSC_SUCCESS` on success and
10982     nonzero on failure.
10983 
10984     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10985 
10986 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10987 @*/
10988 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10989 {
10990   PetscFunctionBegin;
10991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10992   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10993   (((void (**)(void))mat->ops)[op]) = f;
10994   PetscFunctionReturn(PETSC_SUCCESS);
10995 }
10996 
10997 /*@C
10998     MatGetOperation - Gets a matrix operation for any matrix type.
10999 
11000     Not Collective
11001 
11002     Input Parameters:
11003 +   mat - the matrix
11004 -   op - the name of the operation
11005 
11006     Output Parameter:
11007 .   f - the function that provides the operation
11008 
11009     Level: developer
11010 
11011     Usage:
11012 .vb
11013       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11014       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11015 .ve
11016 
11017     Notes:
11018     See the file include/petscmat.h for a complete list of matrix
11019     operations, which all have the form MATOP_<OPERATION>, where
11020     <OPERATION> is the name (in all capital letters) of the
11021     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11022 
11023     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11024 
11025 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11026 @*/
11027 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11028 {
11029   PetscFunctionBegin;
11030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11031   *f = (((void (**)(void))mat->ops)[op]);
11032   PetscFunctionReturn(PETSC_SUCCESS);
11033 }
11034 
11035 /*@
11036     MatHasOperation - Determines whether the given matrix supports the particular operation.
11037 
11038    Not Collective
11039 
11040    Input Parameters:
11041 +  mat - the matrix
11042 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11043 
11044    Output Parameter:
11045 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11046 
11047    Level: advanced
11048 
11049    Note:
11050    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11051 
11052 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11053 @*/
11054 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11055 {
11056   PetscFunctionBegin;
11057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11058   PetscValidBoolPointer(has, 3);
11059   if (mat->ops->hasoperation) {
11060     PetscUseTypeMethod(mat, hasoperation, op, has);
11061   } else {
11062     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11063     else {
11064       *has = PETSC_FALSE;
11065       if (op == MATOP_CREATE_SUBMATRIX) {
11066         PetscMPIInt size;
11067 
11068         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11069         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11070       }
11071     }
11072   }
11073   PetscFunctionReturn(PETSC_SUCCESS);
11074 }
11075 
11076 /*@
11077     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11078 
11079    Collective
11080 
11081    Input Parameter:
11082 .  mat - the matrix
11083 
11084    Output Parameter:
11085 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11086 
11087    Level: beginner
11088 
11089 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11090 @*/
11091 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11092 {
11093   PetscFunctionBegin;
11094   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11095   PetscValidType(mat, 1);
11096   PetscValidBoolPointer(cong, 2);
11097   if (!mat->rmap || !mat->cmap) {
11098     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11099     PetscFunctionReturn(PETSC_SUCCESS);
11100   }
11101   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11102     PetscCall(PetscLayoutSetUp(mat->rmap));
11103     PetscCall(PetscLayoutSetUp(mat->cmap));
11104     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11105     if (*cong) mat->congruentlayouts = 1;
11106     else mat->congruentlayouts = 0;
11107   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11108   PetscFunctionReturn(PETSC_SUCCESS);
11109 }
11110 
11111 PetscErrorCode MatSetInf(Mat A)
11112 {
11113   PetscFunctionBegin;
11114   PetscUseTypeMethod(A, setinf);
11115   PetscFunctionReturn(PETSC_SUCCESS);
11116 }
11117 
11118 /*@C
11119    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
11120    and possibly removes small values from the graph structure.
11121 
11122    Collective
11123 
11124    Input Parameters:
11125 +  A - the matrix
11126 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11127 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11128 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11129 
11130    Output Parameter:
11131 .  graph - the resulting graph
11132 
11133    Level: advanced
11134 
11135 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11136 @*/
11137 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11138 {
11139   PetscFunctionBegin;
11140   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11141   PetscValidType(A, 1);
11142   PetscValidLogicalCollectiveBool(A, scale, 3);
11143   PetscValidPointer(graph, 5);
11144   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11145   PetscFunctionReturn(PETSC_SUCCESS);
11146 }
11147 
11148 /*@
11149   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11150   meaning the same memory is used for the matrix, and no new memory is allocated.
11151 
11152   Collective
11153 
11154   Input Parameter:
11155 . A - the matrix
11156 
11157   Level: intermediate
11158 
11159   Developer Note:
11160   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11161   of the arrays in the data structure are unneeded.
11162 
11163 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11164 @*/
11165 PetscErrorCode MatEliminateZeros(Mat A)
11166 {
11167   PetscFunctionBegin;
11168   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11169   PetscUseTypeMethod(A, eliminatezeros);
11170   PetscFunctionReturn(PETSC_SUCCESS);
11171 }
11172