xref: /petsc/src/mat/interface/matrix.c (revision 2f3c17da234d2f11b148339b59813b2e2c6c1ee0)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](ch_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](ch_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
899   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
900   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
901   PetscFunctionReturn(PETSC_SUCCESS);
902 }
903 
904 /*@
905    MatSetUp - Sets up the internal matrix data structures for later use.
906 
907    Collective
908 
909    Input Parameter:
910 .  A - the matrix
911 
912    Level: intermediate
913 
914    Notes:
915    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
916    setting values in the matrix.
917 
918    If a suitable preallocation routine is used, this function does not need to be called.
919 
920    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
921 
922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
923 @*/
924 PetscErrorCode MatSetUp(Mat A)
925 {
926   PetscFunctionBegin;
927   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
928   if (!((PetscObject)A)->type_name) {
929     PetscMPIInt size;
930 
931     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
932     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
933   }
934   if (!A->preallocated) PetscTryTypeMethod(A, setup);
935   PetscCall(PetscLayoutSetUp(A->rmap));
936   PetscCall(PetscLayoutSetUp(A->cmap));
937   A->preallocated = PETSC_TRUE;
938   PetscFunctionReturn(PETSC_SUCCESS);
939 }
940 
941 #if defined(PETSC_HAVE_SAWS)
942   #include <petscviewersaws.h>
943 #endif
944 
945 /*
946    If threadsafety is on extraneous matrices may be printed
947 
948    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
949 */
950 #if !defined(PETSC_HAVE_THREADSAFETY)
951 static PetscInt insidematview = 0;
952 #endif
953 
954 /*@C
955    MatViewFromOptions - View properties of the matrix based on options set in the options database
956 
957    Collective
958 
959    Input Parameters:
960 +  A - the matrix
961 .  obj - optional additional object that provides the options prefix to use
962 -  name - command line option
963 
964   Options Database Key:
965 .  -mat_view [viewertype]:... - the viewer and its options
966 
967    Level: intermediate
968 
969   Notes:
970 .vb
971     If no value is provided ascii:stdout is used
972        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
973                                                   for example ascii::ascii_info prints just the information about the object not all details
974                                                   unless :append is given filename opens in write mode, overwriting what was already there
975        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
976        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
977        socket[:port]                             defaults to the standard output port
978        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
979 .ve
980 
981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
982 @*/
983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
984 {
985   PetscFunctionBegin;
986   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
987 #if !defined(PETSC_HAVE_THREADSAFETY)
988   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
989 #endif
990   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
991   PetscFunctionReturn(PETSC_SUCCESS);
992 }
993 
994 /*@C
995    MatView - display information about a matrix in a variety ways
996 
997    Collective
998 
999    Input Parameters:
1000 +  mat - the matrix
1001 -  viewer - visualization context
1002 
1003    Options Database Keys:
1004 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1005 .  -mat_view ::ascii_info_detail - Prints more detailed info
1006 .  -mat_view - Prints matrix in ASCII format
1007 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1008 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1009 .  -display <name> - Sets display name (default is host)
1010 .  -draw_pause <sec> - Sets number of seconds to pause after display
1011 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1012 .  -viewer_socket_machine <machine> -
1013 .  -viewer_socket_port <port> -
1014 .  -mat_view binary - save matrix to file in binary format
1015 -  -viewer_binary_filename <name> -
1016 
1017    Level: beginner
1018 
1019   Notes:
1020   The available visualization contexts include
1021 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1022 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1023 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1024 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1025 
1026    The user can open alternative visualization contexts with
1027 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1028 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1029          specified file; corresponding input uses `MatLoad()`
1030 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1031          an X window display
1032 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1033          Currently only the `MATSEQDENSE` and `MATAIJ`
1034          matrix types support the Socket viewer.
1035 
1036    The user can call `PetscViewerPushFormat()` to specify the output
1037    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1038    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1039 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1040 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1041 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1042 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1043          format common among all matrix types
1044 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1045          format (which is in many cases the same as the default)
1046 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1047          size and structure (not the matrix entries)
1048 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1049          the matrix structure
1050 
1051     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1052     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1053 
1054     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1055 
1056     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1057       viewer is used.
1058 
1059       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1060       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1061 
1062       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1063       and then use the following mouse functions.
1064 .vb
1065   left mouse: zoom in
1066   middle mouse: zoom out
1067   right mouse: continue with the simulation
1068 .ve
1069 
1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1071           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1072 @*/
1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1074 {
1075   PetscInt          rows, cols, rbs, cbs;
1076   PetscBool         isascii, isstring, issaws;
1077   PetscViewerFormat format;
1078   PetscMPIInt       size;
1079 
1080   PetscFunctionBegin;
1081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1082   PetscValidType(mat, 1);
1083   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1084   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1085   PetscCheckSameComm(mat, 1, viewer, 2);
1086 
1087   PetscCall(PetscViewerGetFormat(viewer, &format));
1088   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1089   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1090 
1091 #if !defined(PETSC_HAVE_THREADSAFETY)
1092   insidematview++;
1093 #endif
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1097   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");
1098 
1099   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1100   if (isascii) {
1101     if (!mat->preallocated) {
1102       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1103 #if !defined(PETSC_HAVE_THREADSAFETY)
1104       insidematview--;
1105 #endif
1106       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1107       PetscFunctionReturn(PETSC_SUCCESS);
1108     }
1109     if (!mat->assembled) {
1110       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1111 #if !defined(PETSC_HAVE_THREADSAFETY)
1112       insidematview--;
1113 #endif
1114       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1115       PetscFunctionReturn(PETSC_SUCCESS);
1116     }
1117     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1118     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1119       MatNullSpace nullsp, transnullsp;
1120 
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatGetSize(mat, &rows, &cols));
1123       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1124       if (rbs != 1 || cbs != 1) {
1125         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1126         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1127       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1128       if (mat->factortype) {
1129         MatSolverType solver;
1130         PetscCall(MatFactorGetSolverType(mat, &solver));
1131         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1132       }
1133       if (mat->ops->getinfo) {
1134         MatInfo info;
1135         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1136         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1137         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1138       }
1139       PetscCall(MatGetNullSpace(mat, &nullsp));
1140       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1141       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1142       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1143       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1144       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1145       PetscCall(PetscViewerASCIIPushTab(viewer));
1146       PetscCall(MatProductView(mat, viewer));
1147       PetscCall(PetscViewerASCIIPopTab(viewer));
1148     }
1149   } else if (issaws) {
1150 #if defined(PETSC_HAVE_SAWS)
1151     PetscMPIInt rank;
1152 
1153     PetscCall(PetscObjectName((PetscObject)mat));
1154     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1155     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1156 #endif
1157   } else if (isstring) {
1158     const char *type;
1159     PetscCall(MatGetType(mat, &type));
1160     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1161     PetscTryTypeMethod(mat, view, viewer);
1162   }
1163   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1164     PetscCall(PetscViewerASCIIPushTab(viewer));
1165     PetscUseTypeMethod(mat, viewnative, viewer);
1166     PetscCall(PetscViewerASCIIPopTab(viewer));
1167   } else if (mat->ops->view) {
1168     PetscCall(PetscViewerASCIIPushTab(viewer));
1169     PetscUseTypeMethod(mat, view, viewer);
1170     PetscCall(PetscViewerASCIIPopTab(viewer));
1171   }
1172   if (isascii) {
1173     PetscCall(PetscViewerGetFormat(viewer, &format));
1174     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1175   }
1176   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1177 #if !defined(PETSC_HAVE_THREADSAFETY)
1178   insidematview--;
1179 #endif
1180   PetscFunctionReturn(PETSC_SUCCESS);
1181 }
1182 
1183 #if defined(PETSC_USE_DEBUG)
1184   #include <../src/sys/totalview/tv_data_display.h>
1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1186 {
1187   TV_add_row("Local rows", "int", &mat->rmap->n);
1188   TV_add_row("Local columns", "int", &mat->cmap->n);
1189   TV_add_row("Global rows", "int", &mat->rmap->N);
1190   TV_add_row("Global columns", "int", &mat->cmap->N);
1191   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1192   return TV_format_OK;
1193 }
1194 #endif
1195 
1196 /*@C
1197    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1198    with `MatView()`.  The matrix format is determined from the options database.
1199    Generates a parallel MPI matrix if the communicator has more than one
1200    processor.  The default matrix type is `MATAIJ`.
1201 
1202    Collective
1203 
1204    Input Parameters:
1205 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1206             or some related function before a call to `MatLoad()`
1207 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1208 
1209    Options Database Keys:
1210    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1211    block size
1212 .    -matload_block_size <bs> - set block size
1213 
1214    Level: beginner
1215 
1216    Notes:
1217    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1218    `Mat` before calling this routine if you wish to set it from the options database.
1219 
1220    `MatLoad()` automatically loads into the options database any options
1221    given in the file filename.info where filename is the name of the file
1222    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1223    file will be ignored if you use the -viewer_binary_skip_info option.
1224 
1225    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1226    sets the default matrix type AIJ and sets the local and global sizes.
1227    If type and/or size is already set, then the same are used.
1228 
1229    In parallel, each processor can load a subset of rows (or the
1230    entire matrix).  This routine is especially useful when a large
1231    matrix is stored on disk and only part of it is desired on each
1232    processor.  For example, a parallel solver may access only some of
1233    the rows from each processor.  The algorithm used here reads
1234    relatively small blocks of data rather than reading the entire
1235    matrix and then subsetting it.
1236 
1237    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1238    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1239    or the sequence like
1240 .vb
1241     `PetscViewer` v;
1242     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1243     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1244     `PetscViewerSetFromOptions`(v);
1245     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1246     `PetscViewerFileSetName`(v,"datafile");
1247 .ve
1248    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1249 $ -viewer_type {binary, hdf5}
1250 
1251    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1252    and src/mat/tutorials/ex10.c with the second approach.
1253 
1254    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1255    is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1256    Multiple objects, both matrices and vectors, can be stored within the same file.
1257    Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1258 
1259    Most users should not need to know the details of the binary storage
1260    format, since `MatLoad()` and `MatView()` completely hide these details.
1261    But for anyone who is interested, the standard binary matrix storage
1262    format is
1263 
1264 .vb
1265     PetscInt    MAT_FILE_CLASSID
1266     PetscInt    number of rows
1267     PetscInt    number of columns
1268     PetscInt    total number of nonzeros
1269     PetscInt    *number nonzeros in each row
1270     PetscInt    *column indices of all nonzeros (starting index is zero)
1271     PetscScalar *values of all nonzeros
1272 .ve
1273    If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1274    stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1275    case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1276 
1277    PETSc automatically does the byte swapping for
1278    machines that store the bytes reversed. Thus if you write your own binary
1279    read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1280    and `PetscBinaryWrite()` to see how this may be done.
1281 
1282    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1283    Each processor's chunk is loaded independently by its owning MPI process.
1284    Multiple objects, both matrices and vectors, can be stored within the same file.
1285    They are looked up by their PetscObject name.
1286 
1287    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1288    by default the same structure and naming of the AIJ arrays and column count
1289    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1290 $    save example.mat A b -v7.3
1291    can be directly read by this routine (see Reference 1 for details).
1292 
1293    Depending on your MATLAB version, this format might be a default,
1294    otherwise you can set it as default in Preferences.
1295 
1296    Unless -nocompression flag is used to save the file in MATLAB,
1297    PETSc must be configured with ZLIB package.
1298 
1299    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1300 
1301    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1302 
1303    Corresponding `MatView()` is not yet implemented.
1304 
1305    The loaded matrix is actually a transpose of the original one in MATLAB,
1306    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1307    With this format, matrix is automatically transposed by PETSc,
1308    unless the matrix is marked as SPD or symmetric
1309    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1310 
1311    References:
1312 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1313 
1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1315  @*/
1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1317 {
1318   PetscBool flg;
1319 
1320   PetscFunctionBegin;
1321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1322   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1323 
1324   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1325 
1326   flg = PETSC_FALSE;
1327   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1328   if (flg) {
1329     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1330     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1331   }
1332   flg = PETSC_FALSE;
1333   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1334   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1335 
1336   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1337   PetscUseTypeMethod(mat, load, viewer);
1338   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1339   PetscFunctionReturn(PETSC_SUCCESS);
1340 }
1341 
1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1343 {
1344   Mat_Redundant *redund = *redundant;
1345 
1346   PetscFunctionBegin;
1347   if (redund) {
1348     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1349       PetscCall(ISDestroy(&redund->isrow));
1350       PetscCall(ISDestroy(&redund->iscol));
1351       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1352     } else {
1353       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1354       PetscCall(PetscFree(redund->sbuf_j));
1355       PetscCall(PetscFree(redund->sbuf_a));
1356       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1357         PetscCall(PetscFree(redund->rbuf_j[i]));
1358         PetscCall(PetscFree(redund->rbuf_a[i]));
1359       }
1360       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1361     }
1362 
1363     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1364     PetscCall(PetscFree(redund));
1365   }
1366   PetscFunctionReturn(PETSC_SUCCESS);
1367 }
1368 
1369 /*@C
1370    MatDestroy - Frees space taken by a matrix.
1371 
1372    Collective
1373 
1374    Input Parameter:
1375 .  A - the matrix
1376 
1377    Level: beginner
1378 
1379    Developer Note:
1380    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1381    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1382    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1383    if changes are needed here.
1384 
1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1386 @*/
1387 PetscErrorCode MatDestroy(Mat *A)
1388 {
1389   PetscFunctionBegin;
1390   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1391   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1392   if (--((PetscObject)(*A))->refct > 0) {
1393     *A = NULL;
1394     PetscFunctionReturn(PETSC_SUCCESS);
1395   }
1396 
1397   /* if memory was published with SAWs then destroy it */
1398   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1399   PetscTryTypeMethod((*A), destroy);
1400 
1401   PetscCall(PetscFree((*A)->factorprefix));
1402   PetscCall(PetscFree((*A)->defaultvectype));
1403   PetscCall(PetscFree((*A)->defaultrandtype));
1404   PetscCall(PetscFree((*A)->bsizes));
1405   PetscCall(PetscFree((*A)->solvertype));
1406   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1407   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1408   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1409   PetscCall(MatProductClear(*A));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1411   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1413   PetscCall(MatDestroy(&(*A)->schur));
1414   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1415   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1416   PetscCall(PetscHeaderDestroy(A));
1417   PetscFunctionReturn(PETSC_SUCCESS);
1418 }
1419 
1420 /*@C
1421    MatSetValues - Inserts or adds a block of values into a matrix.
1422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1423    MUST be called after all calls to `MatSetValues()` have been completed.
1424 
1425    Not Collective
1426 
1427    Input Parameters:
1428 +  mat - the matrix
1429 .  v - a logically two-dimensional array of values
1430 .  m - the number of rows
1431 .  idxm - the global indices of the rows
1432 .  n - the number of columns
1433 .  idxn - the global indices of the columns
1434 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1435 
1436    Level: beginner
1437 
1438    Notes:
1439    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1440 
1441    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1442    options cannot be mixed without intervening calls to the assembly
1443    routines.
1444 
1445    `MatSetValues()` uses 0-based row and column numbers in Fortran
1446    as well as in C.
1447 
1448    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1449    simply ignored. This allows easily inserting element stiffness matrices
1450    with homogeneous Dirchlet boundary conditions that you don't want represented
1451    in the matrix.
1452 
1453    Efficiency Alert:
1454    The routine `MatSetValuesBlocked()` may offer much better efficiency
1455    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1456 
1457    Developer Note:
1458    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1459    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1460 
1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1462           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1463 @*/
1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1465 {
1466   PetscFunctionBeginHot;
1467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1468   PetscValidType(mat, 1);
1469   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1470   PetscValidIntPointer(idxm, 3);
1471   PetscValidIntPointer(idxn, 5);
1472   MatCheckPreallocated(mat, 1);
1473 
1474   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1475   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1476 
1477   if (PetscDefined(USE_DEBUG)) {
1478     PetscInt i, j;
1479 
1480     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1481     for (i = 0; i < m; i++) {
1482       for (j = 0; j < n; j++) {
1483         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1484 #if defined(PETSC_USE_COMPLEX)
1485           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]);
1486 #else
1487           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]);
1488 #endif
1489       }
1490     }
1491     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);
1492     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);
1493   }
1494 
1495   if (mat->assembled) {
1496     mat->was_assembled = PETSC_TRUE;
1497     mat->assembled     = PETSC_FALSE;
1498   }
1499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1500   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1501   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1502   PetscFunctionReturn(PETSC_SUCCESS);
1503 }
1504 
1505 /*@C
1506    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1507    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508    MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510    Not Collective
1511 
1512    Input Parameters:
1513 +  mat - the matrix
1514 .  v - a logically two-dimensional array of values
1515 .  ism - the rows to provide
1516 .  isn - the columns to provide
1517 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519    Level: beginner
1520 
1521    Notes:
1522    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525    options cannot be mixed without intervening calls to the assembly
1526    routines.
1527 
1528    `MatSetValues()` uses 0-based row and column numbers in Fortran
1529    as well as in C.
1530 
1531    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1532    simply ignored. This allows easily inserting element stiffness matrices
1533    with homogeneous Dirchlet boundary conditions that you don't want represented
1534    in the matrix.
1535 
1536    Efficiency Alert:
1537    The routine `MatSetValuesBlocked()` may offer much better efficiency
1538    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540     This is currently not optimized for any particular `ISType`
1541 
1542    Developer Notes:
1543     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1544                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1545 
1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1547           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1548 @*/
1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1550 {
1551   PetscInt        m, n;
1552   const PetscInt *rows, *cols;
1553 
1554   PetscFunctionBeginHot;
1555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1556   PetscCall(ISGetIndices(ism, &rows));
1557   PetscCall(ISGetIndices(isn, &cols));
1558   PetscCall(ISGetLocalSize(ism, &m));
1559   PetscCall(ISGetLocalSize(isn, &n));
1560   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1561   PetscCall(ISRestoreIndices(ism, &rows));
1562   PetscCall(ISRestoreIndices(isn, &cols));
1563   PetscFunctionReturn(PETSC_SUCCESS);
1564 }
1565 
1566 /*@
1567    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1568         values into a matrix
1569 
1570    Not Collective
1571 
1572    Input Parameters:
1573 +  mat - the matrix
1574 .  row - the (block) row to set
1575 -  v - a logically two-dimensional array of values
1576 
1577    Level: intermediate
1578 
1579    Notes:
1580    The values, `v`, are column-oriented (for the block version) and sorted
1581 
1582    All the nonzeros in the row must be provided
1583 
1584    The matrix must have previously had its column indices set, likely by having been assembled.
1585 
1586    The row must belong to this process
1587 
1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1589           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1590 @*/
1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1592 {
1593   PetscInt globalrow;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1597   PetscValidType(mat, 1);
1598   PetscValidScalarPointer(v, 3);
1599   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1600   PetscCall(MatSetValuesRow(mat, globalrow, v));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606         values into a matrix
1607 
1608    Not Collective
1609 
1610    Input Parameters:
1611 +  mat - the matrix
1612 .  row - the (block) row to set
1613 -  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
1614 
1615    Level: advanced
1616 
1617    Notes:
1618    The values, `v`, are column-oriented for the block version.
1619 
1620    All the nonzeros in the row must be provided
1621 
1622    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1623 
1624    The row must belong to this process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1628 @*/
1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscFunctionBeginHot;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   MatCheckPreallocated(mat, 1);
1635   PetscValidScalarPointer(v, 3);
1636   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1637   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1638   mat->insertmode = INSERT_VALUES;
1639 
1640   if (mat->assembled) {
1641     mat->was_assembled = PETSC_TRUE;
1642     mat->assembled     = PETSC_FALSE;
1643   }
1644   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1645   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1646   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 /*@
1651    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1652      Using structured grid indexing
1653 
1654    Not Collective
1655 
1656    Input Parameters:
1657 +  mat - the matrix
1658 .  m - number of rows being entered
1659 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1660 .  n - number of columns being entered
1661 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1662 .  v - a logically two-dimensional array of values
1663 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1664 
1665    Level: beginner
1666 
1667    Notes:
1668    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1669 
1670    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1671    options cannot be mixed without intervening calls to the assembly
1672    routines.
1673 
1674    The grid coordinates are across the entire grid, not just the local portion
1675 
1676    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1677    as well as in C.
1678 
1679    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1680 
1681    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1682    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1683 
1684    The columns and rows in the stencil passed in MUST be contained within the
1685    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1686    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1687    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1688    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1689 
1690    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1691    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1692    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1693    `DM_BOUNDARY_PERIODIC` boundary type.
1694 
1695    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
1696    a single value per point) you can skip filling those indices.
1697 
1698    Inspired by the structured grid interface to the HYPRE package
1699    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1700 
1701    Efficiency Alert:
1702    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1703    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1704 
1705    Fortran Note:
1706    `idxm` and `idxn` should be declared as
1707 $     MatStencil idxm(4,m),idxn(4,n)
1708    and the values inserted using
1709 .vb
1710     idxm(MatStencil_i,1) = i
1711     idxm(MatStencil_j,1) = j
1712     idxm(MatStencil_k,1) = k
1713     idxm(MatStencil_c,1) = c
1714     etc
1715 .ve
1716 
1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1718           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1719 @*/
1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1721 {
1722   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1723   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1724   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1725 
1726   PetscFunctionBegin;
1727   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1729   PetscValidType(mat, 1);
1730   PetscValidPointer(idxm, 3);
1731   PetscValidPointer(idxn, 5);
1732 
1733   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1734     jdxm = buf;
1735     jdxn = buf + m;
1736   } else {
1737     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1738     jdxm = bufm;
1739     jdxn = bufn;
1740   }
1741   for (i = 0; i < m; i++) {
1742     for (j = 0; j < 3 - sdim; j++) dxm++;
1743     tmp = *dxm++ - starts[0];
1744     for (j = 0; j < dim - 1; j++) {
1745       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1746       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1747     }
1748     if (mat->stencil.noc) dxm++;
1749     jdxm[i] = tmp;
1750   }
1751   for (i = 0; i < n; i++) {
1752     for (j = 0; j < 3 - sdim; j++) dxn++;
1753     tmp = *dxn++ - starts[0];
1754     for (j = 0; j < dim - 1; j++) {
1755       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1756       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1757     }
1758     if (mat->stencil.noc) dxn++;
1759     jdxn[i] = tmp;
1760   }
1761   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1762   PetscCall(PetscFree2(bufm, bufn));
1763   PetscFunctionReturn(PETSC_SUCCESS);
1764 }
1765 
1766 /*@
1767    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1768      Using structured grid indexing
1769 
1770    Not Collective
1771 
1772    Input Parameters:
1773 +  mat - the matrix
1774 .  m - number of rows being entered
1775 .  idxm - grid coordinates for matrix rows being entered
1776 .  n - number of columns being entered
1777 .  idxn - grid coordinates for matrix columns being entered
1778 .  v - a logically two-dimensional array of values
1779 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1780 
1781    Level: beginner
1782 
1783    Notes:
1784    By default the values, `v`, are row-oriented and unsorted.
1785    See `MatSetOption()` for other options.
1786 
1787    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1788    options cannot be mixed without intervening calls to the assembly
1789    routines.
1790 
1791    The grid coordinates are across the entire grid, not just the local portion
1792 
1793    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1794    as well as in C.
1795 
1796    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1797 
1798    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1799    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1800 
1801    The columns and rows in the stencil passed in MUST be contained within the
1802    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1803    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1804    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1805    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1806 
1807    Negative indices may be passed in idxm and idxn, these rows and columns are
1808    simply ignored. This allows easily inserting element stiffness matrices
1809    with homogeneous Dirchlet boundary conditions that you don't want represented
1810    in the matrix.
1811 
1812    Inspired by the structured grid interface to the HYPRE package
1813    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1814 
1815    Fortran Note:
1816    `idxm` and `idxn` should be declared as
1817 $     MatStencil idxm(4,m),idxn(4,n)
1818    and the values inserted using
1819 .vb
1820     idxm(MatStencil_i,1) = i
1821     idxm(MatStencil_j,1) = j
1822     idxm(MatStencil_k,1) = k
1823    etc
1824 .ve
1825 
1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1827           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1828           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1829 @*/
1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1831 {
1832   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1833   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1834   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1835 
1836   PetscFunctionBegin;
1837   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1839   PetscValidType(mat, 1);
1840   PetscValidPointer(idxm, 3);
1841   PetscValidPointer(idxn, 5);
1842   PetscValidScalarPointer(v, 6);
1843 
1844   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1845     jdxm = buf;
1846     jdxn = buf + m;
1847   } else {
1848     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1849     jdxm = bufm;
1850     jdxn = bufn;
1851   }
1852   for (i = 0; i < m; i++) {
1853     for (j = 0; j < 3 - sdim; j++) dxm++;
1854     tmp = *dxm++ - starts[0];
1855     for (j = 0; j < sdim - 1; j++) {
1856       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1857       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1858     }
1859     dxm++;
1860     jdxm[i] = tmp;
1861   }
1862   for (i = 0; i < n; i++) {
1863     for (j = 0; j < 3 - sdim; j++) dxn++;
1864     tmp = *dxn++ - starts[0];
1865     for (j = 0; j < sdim - 1; j++) {
1866       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1867       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1868     }
1869     dxn++;
1870     jdxn[i] = tmp;
1871   }
1872   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1873   PetscCall(PetscFree2(bufm, bufn));
1874   PetscFunctionReturn(PETSC_SUCCESS);
1875 }
1876 
1877 /*@
1878    MatSetStencil - Sets the grid information for setting values into a matrix via
1879         `MatSetValuesStencil()`
1880 
1881    Not Collective
1882 
1883    Input Parameters:
1884 +  mat - the matrix
1885 .  dim - dimension of the grid 1, 2, or 3
1886 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1887 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1888 -  dof - number of degrees of freedom per node
1889 
1890    Level: beginner
1891 
1892    Notes:
1893    Inspired by the structured grid interface to the HYPRE package
1894    (www.llnl.gov/CASC/hyper)
1895 
1896    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1897    user.
1898 
1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1900           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1901 @*/
1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1903 {
1904   PetscFunctionBegin;
1905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1906   PetscValidIntPointer(dims, 3);
1907   PetscValidIntPointer(starts, 4);
1908 
1909   mat->stencil.dim = dim + (dof > 1);
1910   for (PetscInt i = 0; i < dim; i++) {
1911     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1912     mat->stencil.starts[i] = starts[dim - i - 1];
1913   }
1914   mat->stencil.dims[dim]   = dof;
1915   mat->stencil.starts[dim] = 0;
1916   mat->stencil.noc         = (PetscBool)(dof == 1);
1917   PetscFunctionReturn(PETSC_SUCCESS);
1918 }
1919 
1920 /*@C
1921    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1922 
1923    Not Collective
1924 
1925    Input Parameters:
1926 +  mat - the matrix
1927 .  v - a logically two-dimensional array of values
1928 .  m  - the number of block rows
1929 .  idxm - the global block indices
1930 .  n - the number of block columns
1931 .  idxn - the global block indices
1932 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1933 
1934    Level: intermediate
1935 
1936    Notes:
1937    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1938    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1939 
1940    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1941    NOT the total number of rows/columns; for example, if the block size is 2 and
1942    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1943    The values in idxm would be 1 2; that is the first index for each block divided by
1944    the block size.
1945 
1946    You must call `MatSetBlockSize()` when constructing this matrix (before
1947    preallocating it).
1948 
1949    By default the values, `v`, are row-oriented, so the layout of
1950    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1951 
1952    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1953    options cannot be mixed without intervening calls to the assembly
1954    routines.
1955 
1956    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1957    as well as in C.
1958 
1959    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1960    simply ignored. This allows easily inserting element stiffness matrices
1961    with homogeneous Dirchlet boundary conditions that you don't want represented
1962    in the matrix.
1963 
1964    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1965    internal searching must be done to determine where to place the
1966    data in the matrix storage space.  By instead inserting blocks of
1967    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1968    reduced.
1969 
1970    Example:
1971 .vb
1972    Suppose m=n=2 and block size(bs) = 2 The array is
1973 
1974    1  2  | 3  4
1975    5  6  | 7  8
1976    - - - | - - -
1977    9  10 | 11 12
1978    13 14 | 15 16
1979 
1980    v[] should be passed in like
1981    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1982 
1983   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1984    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1985 .ve
1986 
1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1988 @*/
1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1990 {
1991   PetscFunctionBeginHot;
1992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1993   PetscValidType(mat, 1);
1994   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1995   PetscValidIntPointer(idxm, 3);
1996   PetscValidIntPointer(idxn, 5);
1997   MatCheckPreallocated(mat, 1);
1998   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1999   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2000   if (PetscDefined(USE_DEBUG)) {
2001     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2002     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2003   }
2004   if (PetscDefined(USE_DEBUG)) {
2005     PetscInt rbs, cbs, M, N, i;
2006     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2007     PetscCall(MatGetSize(mat, &M, &N));
2008     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);
2009     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);
2010   }
2011   if (mat->assembled) {
2012     mat->was_assembled = PETSC_TRUE;
2013     mat->assembled     = PETSC_FALSE;
2014   }
2015   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2016   if (mat->ops->setvaluesblocked) {
2017     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2018   } else {
2019     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2020     PetscInt i, j, bs, cbs;
2021 
2022     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2023     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2024       iidxm = buf;
2025       iidxn = buf + m * bs;
2026     } else {
2027       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2028       iidxm = bufr;
2029       iidxn = bufc;
2030     }
2031     for (i = 0; i < m; i++) {
2032       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2033     }
2034     if (m != n || bs != cbs || idxm != idxn) {
2035       for (i = 0; i < n; i++) {
2036         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2037       }
2038     } else iidxn = iidxm;
2039     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2040     PetscCall(PetscFree2(bufr, bufc));
2041   }
2042   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2043   PetscFunctionReturn(PETSC_SUCCESS);
2044 }
2045 
2046 /*@C
2047    MatGetValues - Gets a block of local values from a matrix.
2048 
2049    Not Collective; can only return values that are owned by the give process
2050 
2051    Input Parameters:
2052 +  mat - the matrix
2053 .  v - a logically two-dimensional array for storing the values
2054 .  m  - the number of rows
2055 .  idxm - the  global indices of the rows
2056 .  n - the number of columns
2057 -  idxn - the global indices of the columns
2058 
2059    Level: advanced
2060 
2061    Notes:
2062      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2063      The values, `v`, are then returned in a row-oriented format,
2064      analogous to that used by default in `MatSetValues()`.
2065 
2066      `MatGetValues()` uses 0-based row and column numbers in
2067      Fortran as well as in C.
2068 
2069      `MatGetValues()` requires that the matrix has been assembled
2070      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2071      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2072      without intermediate matrix assembly.
2073 
2074      Negative row or column indices will be ignored and those locations in `v` will be
2075      left unchanged.
2076 
2077      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2078      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2079      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2080 
2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2082 @*/
2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2084 {
2085   PetscFunctionBegin;
2086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2087   PetscValidType(mat, 1);
2088   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2089   PetscValidIntPointer(idxm, 3);
2090   PetscValidIntPointer(idxn, 5);
2091   PetscValidScalarPointer(v, 6);
2092   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2093   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2094   MatCheckPreallocated(mat, 1);
2095 
2096   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2097   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2098   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2099   PetscFunctionReturn(PETSC_SUCCESS);
2100 }
2101 
2102 /*@C
2103    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2104      defined previously by `MatSetLocalToGlobalMapping()`
2105 
2106    Not Collective
2107 
2108    Input Parameters:
2109 +  mat - the matrix
2110 .  nrow - number of rows
2111 .  irow - the row local indices
2112 .  ncol - number of columns
2113 -  icol - the column local indices
2114 
2115    Output Parameter:
2116 .  y -  a logically two-dimensional array of values
2117 
2118    Level: advanced
2119 
2120    Notes:
2121      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2122 
2123      This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2124      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2125      determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2126      with `MatSetLocalToGlobalMapping()`.
2127 
2128    Developer Note:
2129       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2130       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2131 
2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2133           `MatSetValuesLocal()`, `MatGetValues()`
2134 @*/
2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2136 {
2137   PetscFunctionBeginHot;
2138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2139   PetscValidType(mat, 1);
2140   MatCheckPreallocated(mat, 1);
2141   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2142   PetscValidIntPointer(irow, 3);
2143   PetscValidIntPointer(icol, 5);
2144   if (PetscDefined(USE_DEBUG)) {
2145     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2146     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2147   }
2148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2149   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2150   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2151   else {
2152     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2153     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2154       irowm = buf;
2155       icolm = buf + nrow;
2156     } else {
2157       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2158       irowm = bufr;
2159       icolm = bufc;
2160     }
2161     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2163     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2164     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2165     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2166     PetscCall(PetscFree2(bufr, bufc));
2167   }
2168   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2169   PetscFunctionReturn(PETSC_SUCCESS);
2170 }
2171 
2172 /*@
2173   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2174   the same size. Currently, this can only be called once and creates the given matrix.
2175 
2176   Not Collective
2177 
2178   Input Parameters:
2179 + mat - the matrix
2180 . nb - the number of blocks
2181 . bs - the number of rows (and columns) in each block
2182 . rows - a concatenation of the rows for each block
2183 - v - a concatenation of logically two-dimensional arrays of values
2184 
2185   Level: advanced
2186 
2187   Note:
2188   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2189 
2190   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2191 
2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2193           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2194 @*/
2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2196 {
2197   PetscFunctionBegin;
2198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2199   PetscValidType(mat, 1);
2200   PetscValidIntPointer(rows, 4);
2201   PetscValidScalarPointer(v, 5);
2202   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2203 
2204   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2205   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2206   else {
2207     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2208   }
2209   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2210   PetscFunctionReturn(PETSC_SUCCESS);
2211 }
2212 
2213 /*@
2214    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2215    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2216    using a local (per-processor) numbering.
2217 
2218    Not Collective
2219 
2220    Input Parameters:
2221 +  x - the matrix
2222 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2223 -  cmapping - column mapping
2224 
2225    Level: intermediate
2226 
2227    Note:
2228    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2229 
2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2236   PetscValidType(x, 1);
2237   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2238   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2239   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2240   else {
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2242     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2243   }
2244   PetscFunctionReturn(PETSC_SUCCESS);
2245 }
2246 
2247 /*@
2248    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2249 
2250    Not Collective
2251 
2252    Input Parameter:
2253 .  A - the matrix
2254 
2255    Output Parameters:
2256 + rmapping - row mapping
2257 - cmapping - column mapping
2258 
2259    Level: advanced
2260 
2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2262 @*/
2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2264 {
2265   PetscFunctionBegin;
2266   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2267   PetscValidType(A, 1);
2268   if (rmapping) {
2269     PetscValidPointer(rmapping, 2);
2270     *rmapping = A->rmap->mapping;
2271   }
2272   if (cmapping) {
2273     PetscValidPointer(cmapping, 3);
2274     *cmapping = A->cmap->mapping;
2275   }
2276   PetscFunctionReturn(PETSC_SUCCESS);
2277 }
2278 
2279 /*@
2280    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2281 
2282    Logically Collective
2283 
2284    Input Parameters:
2285 +  A - the matrix
2286 . rmap - row layout
2287 - cmap - column layout
2288 
2289    Level: advanced
2290 
2291    Note:
2292    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2293 
2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2295 @*/
2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2297 {
2298   PetscFunctionBegin;
2299   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2300   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2301   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2302   PetscFunctionReturn(PETSC_SUCCESS);
2303 }
2304 
2305 /*@
2306    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2307 
2308    Not Collective
2309 
2310    Input Parameter:
2311 .  A - the matrix
2312 
2313    Output Parameters:
2314 + rmap - row layout
2315 - cmap - column layout
2316 
2317    Level: advanced
2318 
2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2320 @*/
2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2322 {
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2325   PetscValidType(A, 1);
2326   if (rmap) {
2327     PetscValidPointer(rmap, 2);
2328     *rmap = A->rmap;
2329   }
2330   if (cmap) {
2331     PetscValidPointer(cmap, 3);
2332     *cmap = A->cmap;
2333   }
2334   PetscFunctionReturn(PETSC_SUCCESS);
2335 }
2336 
2337 /*@C
2338    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2339    using a local numbering of the nodes.
2340 
2341    Not Collective
2342 
2343    Input Parameters:
2344 +  mat - the matrix
2345 .  nrow - number of rows
2346 .  irow - the row local indices
2347 .  ncol - number of columns
2348 .  icol - the column local indices
2349 .  y -  a logically two-dimensional array of values
2350 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2351 
2352    Level: intermediate
2353 
2354    Notes:
2355    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2356       `MatSetUp()` before using this routine
2357 
2358    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2359 
2360    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2361    options cannot be mixed without intervening calls to the assembly
2362    routines.
2363 
2364    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2365    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2366 
2367    Developer Note:
2368     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2369                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2370 
2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2372           `MatGetValuesLocal()`
2373 @*/
2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2375 {
2376   PetscFunctionBeginHot;
2377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2378   PetscValidType(mat, 1);
2379   MatCheckPreallocated(mat, 1);
2380   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2381   PetscValidIntPointer(irow, 3);
2382   PetscValidIntPointer(icol, 5);
2383   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2384   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2385   if (PetscDefined(USE_DEBUG)) {
2386     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2387     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2388   }
2389 
2390   if (mat->assembled) {
2391     mat->was_assembled = PETSC_TRUE;
2392     mat->assembled     = PETSC_FALSE;
2393   }
2394   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2395   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2396   else {
2397     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2398     const PetscInt *irowm, *icolm;
2399 
2400     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2401       bufr  = buf;
2402       bufc  = buf + nrow;
2403       irowm = bufr;
2404       icolm = bufc;
2405     } else {
2406       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2407       irowm = bufr;
2408       icolm = bufc;
2409     }
2410     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2411     else irowm = irow;
2412     if (mat->cmap->mapping) {
2413       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2414         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2415       } else icolm = irowm;
2416     } else icolm = icol;
2417     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2418     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2419   }
2420   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2421   PetscFunctionReturn(PETSC_SUCCESS);
2422 }
2423 
2424 /*@C
2425    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2426    using a local ordering of the nodes a block at a time.
2427 
2428    Not Collective
2429 
2430    Input Parameters:
2431 +  x - the matrix
2432 .  nrow - number of rows
2433 .  irow - the row local indices
2434 .  ncol - number of columns
2435 .  icol - the column local indices
2436 .  y -  a logically two-dimensional array of values
2437 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2438 
2439    Level: intermediate
2440 
2441    Notes:
2442    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2443       `MatSetUp()` before using this routine
2444 
2445    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2446       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2447 
2448    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2449    options cannot be mixed without intervening calls to the assembly
2450    routines.
2451 
2452    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2453    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2454 
2455    Developer Note:
2456     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2457                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2458 
2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2460           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2461 @*/
2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2463 {
2464   PetscFunctionBeginHot;
2465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2466   PetscValidType(mat, 1);
2467   MatCheckPreallocated(mat, 1);
2468   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2469   PetscValidIntPointer(irow, 3);
2470   PetscValidIntPointer(icol, 5);
2471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2473   if (PetscDefined(USE_DEBUG)) {
2474     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2475     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);
2476   }
2477 
2478   if (mat->assembled) {
2479     mat->was_assembled = PETSC_TRUE;
2480     mat->assembled     = PETSC_FALSE;
2481   }
2482   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2483     PetscInt irbs, rbs;
2484     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2485     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2486     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2487   }
2488   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2489     PetscInt icbs, cbs;
2490     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2491     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2492     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2493   }
2494   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2495   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2496   else {
2497     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2498     const PetscInt *irowm, *icolm;
2499 
2500     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2501       bufr  = buf;
2502       bufc  = buf + nrow;
2503       irowm = bufr;
2504       icolm = bufc;
2505     } else {
2506       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2507       irowm = bufr;
2508       icolm = bufc;
2509     }
2510     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2511     else irowm = irow;
2512     if (mat->cmap->mapping) {
2513       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2514         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2515       } else icolm = irowm;
2516     } else icolm = icol;
2517     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2518     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2519   }
2520   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2521   PetscFunctionReturn(PETSC_SUCCESS);
2522 }
2523 
2524 /*@
2525    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2526 
2527    Collective
2528 
2529    Input Parameters:
2530 +  mat - the matrix
2531 -  x   - the vector to be multiplied
2532 
2533    Output Parameter:
2534 .  y - the result
2535 
2536    Level: developer
2537 
2538    Note:
2539    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2540    call `MatMultDiagonalBlock`(A,y,y).
2541 
2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2543 @*/
2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2545 {
2546   PetscFunctionBegin;
2547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2548   PetscValidType(mat, 1);
2549   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2550   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2551 
2552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2554   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2555   MatCheckPreallocated(mat, 1);
2556 
2557   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2558   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2559   PetscFunctionReturn(PETSC_SUCCESS);
2560 }
2561 
2562 /*@
2563    MatMult - Computes the matrix-vector product, y = Ax.
2564 
2565    Neighbor-wise Collective
2566 
2567    Input Parameters:
2568 +  mat - the matrix
2569 -  x   - the vector to be multiplied
2570 
2571    Output Parameter:
2572 .  y - the result
2573 
2574    Level: beginner
2575 
2576    Note:
2577    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2578    call `MatMult`(A,y,y).
2579 
2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2581 @*/
2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2583 {
2584   PetscFunctionBegin;
2585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2586   PetscValidType(mat, 1);
2587   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2588   VecCheckAssembled(x);
2589   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2592   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2593   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);
2594   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);
2595   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);
2596   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);
2597   PetscCall(VecSetErrorIfLocked(y, 3));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2599   MatCheckPreallocated(mat, 1);
2600 
2601   PetscCall(VecLockReadPush(x));
2602   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2603   PetscUseTypeMethod(mat, mult, x, y);
2604   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2605   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2606   PetscCall(VecLockReadPop(x));
2607   PetscFunctionReturn(PETSC_SUCCESS);
2608 }
2609 
2610 /*@
2611    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2612 
2613    Neighbor-wise Collective
2614 
2615    Input Parameters:
2616 +  mat - the matrix
2617 -  x   - the vector to be multiplied
2618 
2619    Output Parameter:
2620 .  y - the result
2621 
2622    Level: beginner
2623 
2624    Notes:
2625    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2626    call `MatMultTranspose`(A,y,y).
2627 
2628    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2629    use `MatMultHermitianTranspose()`
2630 
2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2632 @*/
2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2634 {
2635   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2636 
2637   PetscFunctionBegin;
2638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2639   PetscValidType(mat, 1);
2640   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2641   VecCheckAssembled(x);
2642   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2643 
2644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2646   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2647   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);
2648   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);
2649   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);
2650   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);
2651   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2652   MatCheckPreallocated(mat, 1);
2653 
2654   if (!mat->ops->multtranspose) {
2655     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2656     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);
2657   } else op = mat->ops->multtranspose;
2658   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2659   PetscCall(VecLockReadPush(x));
2660   PetscCall((*op)(mat, x, y));
2661   PetscCall(VecLockReadPop(x));
2662   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2663   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2664   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2665   PetscFunctionReturn(PETSC_SUCCESS);
2666 }
2667 
2668 /*@
2669    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2670 
2671    Neighbor-wise Collective
2672 
2673    Input Parameters:
2674 +  mat - the matrix
2675 -  x   - the vector to be multilplied
2676 
2677    Output Parameter:
2678 .  y - the result
2679 
2680    Level: beginner
2681 
2682    Notes:
2683    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2684    call `MatMultHermitianTranspose`(A,y,y).
2685 
2686    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2687 
2688    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2689 
2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2691 @*/
2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2693 {
2694   PetscFunctionBegin;
2695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2696   PetscValidType(mat, 1);
2697   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2698   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2699 
2700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2702   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2703   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);
2704   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);
2705   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);
2706   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);
2707   MatCheckPreallocated(mat, 1);
2708 
2709   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2710 #if defined(PETSC_USE_COMPLEX)
2711   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2712     PetscCall(VecLockReadPush(x));
2713     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2714     else PetscUseTypeMethod(mat, mult, x, y);
2715     PetscCall(VecLockReadPop(x));
2716   } else {
2717     Vec w;
2718     PetscCall(VecDuplicate(x, &w));
2719     PetscCall(VecCopy(x, w));
2720     PetscCall(VecConjugate(w));
2721     PetscCall(MatMultTranspose(mat, w, y));
2722     PetscCall(VecDestroy(&w));
2723     PetscCall(VecConjugate(y));
2724   }
2725   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2726 #else
2727   PetscCall(MatMultTranspose(mat, x, y));
2728 #endif
2729   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2730   PetscFunctionReturn(PETSC_SUCCESS);
2731 }
2732 
2733 /*@
2734     MatMultAdd -  Computes v3 = v2 + A * v1.
2735 
2736     Neighbor-wise Collective
2737 
2738     Input Parameters:
2739 +   mat - the matrix
2740 .   v1 - the vector to be multiplied by `mat`
2741 -   v2 - the vector to be added to the result
2742 
2743     Output Parameter:
2744 .   v3 - the result
2745 
2746     Level: beginner
2747 
2748     Note:
2749     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2750     call `MatMultAdd`(A,v1,v2,v1).
2751 
2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2753 @*/
2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2755 {
2756   PetscFunctionBegin;
2757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2758   PetscValidType(mat, 1);
2759   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2760   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2761   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2762 
2763   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2764   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2765   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);
2766   /* 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);
2767      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); */
2768   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);
2769   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);
2770   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2771   MatCheckPreallocated(mat, 1);
2772 
2773   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2774   PetscCall(VecLockReadPush(v1));
2775   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2776   PetscCall(VecLockReadPop(v1));
2777   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2778   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2779   PetscFunctionReturn(PETSC_SUCCESS);
2780 }
2781 
2782 /*@
2783    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2784 
2785    Neighbor-wise Collective
2786 
2787    Input Parameters:
2788 +  mat - the matrix
2789 .  v1 - the vector to be multiplied by the transpose of the matrix
2790 -  v2 - the vector to be added to the result
2791 
2792    Output Parameter:
2793 .  v3 - the result
2794 
2795    Level: beginner
2796 
2797    Note:
2798    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2799    call `MatMultTransposeAdd`(A,v1,v2,v1).
2800 
2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2802 @*/
2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2804 {
2805   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2806 
2807   PetscFunctionBegin;
2808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2809   PetscValidType(mat, 1);
2810   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2811   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2812   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2813 
2814   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2815   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2816   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);
2817   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);
2818   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);
2819   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2820   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2821   MatCheckPreallocated(mat, 1);
2822 
2823   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2824   PetscCall(VecLockReadPush(v1));
2825   PetscCall((*op)(mat, v1, v2, v3));
2826   PetscCall(VecLockReadPop(v1));
2827   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2828   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2829   PetscFunctionReturn(PETSC_SUCCESS);
2830 }
2831 
2832 /*@
2833    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2834 
2835    Neighbor-wise Collective
2836 
2837    Input Parameters:
2838 +  mat - the matrix
2839 .  v1 - the vector to be multiplied by the Hermitian transpose
2840 -  v2 - the vector to be added to the result
2841 
2842    Output Parameter:
2843 .  v3 - the result
2844 
2845    Level: beginner
2846 
2847    Note:
2848    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2849    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2850 
2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2852 @*/
2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2854 {
2855   PetscFunctionBegin;
2856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2857   PetscValidType(mat, 1);
2858   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2859   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2860   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2861 
2862   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2863   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2864   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2865   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);
2866   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);
2867   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);
2868   MatCheckPreallocated(mat, 1);
2869 
2870   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2871   PetscCall(VecLockReadPush(v1));
2872   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2873   else {
2874     Vec w, z;
2875     PetscCall(VecDuplicate(v1, &w));
2876     PetscCall(VecCopy(v1, w));
2877     PetscCall(VecConjugate(w));
2878     PetscCall(VecDuplicate(v3, &z));
2879     PetscCall(MatMultTranspose(mat, w, z));
2880     PetscCall(VecDestroy(&w));
2881     PetscCall(VecConjugate(z));
2882     if (v2 != v3) {
2883       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2884     } else {
2885       PetscCall(VecAXPY(v3, 1.0, z));
2886     }
2887     PetscCall(VecDestroy(&z));
2888   }
2889   PetscCall(VecLockReadPop(v1));
2890   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2891   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2892   PetscFunctionReturn(PETSC_SUCCESS);
2893 }
2894 
2895 /*@C
2896    MatGetFactorType - gets the type of factorization it is
2897 
2898    Not Collective
2899 
2900    Input Parameter:
2901 .  mat - the matrix
2902 
2903    Output Parameter:
2904 .  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`
2905 
2906    Level: intermediate
2907 
2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2909           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2910 @*/
2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2912 {
2913   PetscFunctionBegin;
2914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2915   PetscValidType(mat, 1);
2916   PetscValidPointer(t, 2);
2917   *t = mat->factortype;
2918   PetscFunctionReturn(PETSC_SUCCESS);
2919 }
2920 
2921 /*@C
2922    MatSetFactorType - sets the type of factorization it is
2923 
2924    Logically Collective
2925 
2926    Input Parameters:
2927 +  mat - the matrix
2928 -  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`
2929 
2930    Level: intermediate
2931 
2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2933           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2934 @*/
2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2936 {
2937   PetscFunctionBegin;
2938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2939   PetscValidType(mat, 1);
2940   mat->factortype = t;
2941   PetscFunctionReturn(PETSC_SUCCESS);
2942 }
2943 
2944 /*@C
2945    MatGetInfo - Returns information about matrix storage (number of
2946    nonzeros, memory, etc.).
2947 
2948    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2949 
2950    Input Parameters:
2951 +  mat - the matrix
2952 -  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)
2953 
2954    Output Parameter:
2955 .  info - matrix information context
2956 
2957    Options Database Key:
2958 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2959 
2960    Notes:
2961    The `MatInfo` context contains a variety of matrix data, including
2962    number of nonzeros allocated and used, number of mallocs during
2963    matrix assembly, etc.  Additional information for factored matrices
2964    is provided (such as the fill ratio, number of mallocs during
2965    factorization, etc.).
2966 
2967    Example:
2968    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2969    data within the MatInfo context.  For example,
2970 .vb
2971       MatInfo info;
2972       Mat     A;
2973       double  mal, nz_a, nz_u;
2974 
2975       MatGetInfo(A, MAT_LOCAL, &info);
2976       mal  = info.mallocs;
2977       nz_a = info.nz_allocated;
2978 .ve
2979 
2980    Fortran users should declare info as a double precision
2981    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2982    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2983    a complete list of parameter names.
2984 .vb
2985       double  precision info(MAT_INFO_SIZE)
2986       double  precision mal, nz_a
2987       Mat     A
2988       integer ierr
2989 
2990       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2991       mal = info(MAT_INFO_MALLOCS)
2992       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2993 .ve
2994 
2995     Level: intermediate
2996 
2997     Developer Note:
2998     The Fortran interface is not autogenerated as the
2999     interface definition cannot be generated correctly [due to `MatInfo` argument]
3000 
3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3002 @*/
3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3004 {
3005   PetscFunctionBegin;
3006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3007   PetscValidType(mat, 1);
3008   PetscValidPointer(info, 3);
3009   MatCheckPreallocated(mat, 1);
3010   PetscUseTypeMethod(mat, getinfo, flag, info);
3011   PetscFunctionReturn(PETSC_SUCCESS);
3012 }
3013 
3014 /*
3015    This is used by external packages where it is not easy to get the info from the actual
3016    matrix factorization.
3017 */
3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3019 {
3020   PetscFunctionBegin;
3021   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3022   PetscFunctionReturn(PETSC_SUCCESS);
3023 }
3024 
3025 /*@C
3026    MatLUFactor - Performs in-place LU factorization of matrix.
3027 
3028    Collective
3029 
3030    Input Parameters:
3031 +  mat - the matrix
3032 .  row - row permutation
3033 .  col - column permutation
3034 -  info - options for factorization, includes
3035 .vb
3036           fill - expected fill as ratio of original fill.
3037           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3038                    Run with the option -info to determine an optimal value to use
3039 .ve
3040    Level: developer
3041 
3042    Notes:
3043    Most users should employ the `KSP` interface for linear solvers
3044    instead of working directly with matrix algebra routines such as this.
3045    See, e.g., `KSPCreate()`.
3046 
3047    This changes the state of the matrix to a factored matrix; it cannot be used
3048    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3049 
3050    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3051    when not using `KSP`.
3052 
3053    Developer Note:
3054    The Fortran interface is not autogenerated as the
3055    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3056 
3057 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3058           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3059 @*/
3060 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3061 {
3062   MatFactorInfo tinfo;
3063 
3064   PetscFunctionBegin;
3065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3066   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3067   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3068   if (info) PetscValidPointer(info, 4);
3069   PetscValidType(mat, 1);
3070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3071   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3072   MatCheckPreallocated(mat, 1);
3073   if (!info) {
3074     PetscCall(MatFactorInfoInitialize(&tinfo));
3075     info = &tinfo;
3076   }
3077 
3078   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3079   PetscUseTypeMethod(mat, lufactor, row, col, info);
3080   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3081   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3082   PetscFunctionReturn(PETSC_SUCCESS);
3083 }
3084 
3085 /*@C
3086    MatILUFactor - Performs in-place ILU factorization of matrix.
3087 
3088    Collective
3089 
3090    Input Parameters:
3091 +  mat - the matrix
3092 .  row - row permutation
3093 .  col - column permutation
3094 -  info - structure containing
3095 .vb
3096       levels - number of levels of fill.
3097       expected fill - as ratio of original fill.
3098       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3099                 missing diagonal entries)
3100 .ve
3101 
3102    Level: developer
3103 
3104    Notes:
3105    Most users should employ the `KSP` interface for linear solvers
3106    instead of working directly with matrix algebra routines such as this.
3107    See, e.g., `KSPCreate()`.
3108 
3109    Probably really in-place only when level of fill is zero, otherwise allocates
3110    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3111    when not using `KSP`.
3112 
3113    Developer Note:
3114    The Fortran interface is not autogenerated as the
3115    interface definition cannot be generated correctly [due to MatFactorInfo]
3116 
3117 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3118 @*/
3119 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3120 {
3121   PetscFunctionBegin;
3122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3123   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3124   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3125   PetscValidPointer(info, 4);
3126   PetscValidType(mat, 1);
3127   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3129   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3130   MatCheckPreallocated(mat, 1);
3131 
3132   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3133   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3134   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3135   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3136   PetscFunctionReturn(PETSC_SUCCESS);
3137 }
3138 
3139 /*@C
3140    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3141    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3142 
3143    Collective
3144 
3145    Input Parameters:
3146 +  fact - the factor matrix obtained with `MatGetFactor()`
3147 .  mat - the matrix
3148 .  row - the row permutation
3149 .  col - the column permutation
3150 -  info - options for factorization, includes
3151 .vb
3152           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3153           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3154 .ve
3155 
3156    Level: developer
3157 
3158    Notes:
3159     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3160 
3161    Most users should employ the simplified `KSP` interface for linear solvers
3162    instead of working directly with matrix algebra routines such as this.
3163    See, e.g., `KSPCreate()`.
3164 
3165    Developer Note:
3166    The Fortran interface is not autogenerated as the
3167    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3168 
3169 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3170 @*/
3171 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3172 {
3173   MatFactorInfo tinfo;
3174 
3175   PetscFunctionBegin;
3176   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3178   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3179   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3180   if (info) PetscValidPointer(info, 5);
3181   PetscValidType(fact, 1);
3182   PetscValidType(mat, 2);
3183   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3184   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3185   MatCheckPreallocated(mat, 2);
3186   if (!info) {
3187     PetscCall(MatFactorInfoInitialize(&tinfo));
3188     info = &tinfo;
3189   }
3190 
3191   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3192   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3193   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3194   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3195   PetscFunctionReturn(PETSC_SUCCESS);
3196 }
3197 
3198 /*@C
3199    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3200    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3201 
3202    Collective
3203 
3204    Input Parameters:
3205 +  fact - the factor matrix obtained with `MatGetFactor()`
3206 .  mat - the matrix
3207 -  info - options for factorization
3208 
3209    Level: developer
3210 
3211    Notes:
3212    See `MatLUFactor()` for in-place factorization.  See
3213    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3214 
3215    Most users should employ the `KSP` interface for linear solvers
3216    instead of working directly with matrix algebra routines such as this.
3217    See, e.g., `KSPCreate()`.
3218 
3219     Developer Note:
3220     The Fortran interface is not autogenerated as the
3221     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3222 
3223 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3224 @*/
3225 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3226 {
3227   MatFactorInfo tinfo;
3228 
3229   PetscFunctionBegin;
3230   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3231   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3232   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3233   PetscValidType(fact, 1);
3234   PetscValidType(mat, 2);
3235   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3236   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,
3237              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3238 
3239   MatCheckPreallocated(mat, 2);
3240   if (!info) {
3241     PetscCall(MatFactorInfoInitialize(&tinfo));
3242     info = &tinfo;
3243   }
3244 
3245   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3246   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3247   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3248   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3249   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3250   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3251   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3252   PetscFunctionReturn(PETSC_SUCCESS);
3253 }
3254 
3255 /*@C
3256    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3257    symmetric matrix.
3258 
3259    Collective
3260 
3261    Input Parameters:
3262 +  mat - the matrix
3263 .  perm - row and column permutations
3264 -  f - expected fill as ratio of original fill
3265 
3266    Level: developer
3267 
3268    Notes:
3269    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3270    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3271 
3272    Most users should employ the `KSP` interface for linear solvers
3273    instead of working directly with matrix algebra routines such as this.
3274    See, e.g., `KSPCreate()`.
3275 
3276    Developer Note:
3277    The Fortran interface is not autogenerated as the
3278    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3279 
3280 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3281           `MatGetOrdering()`
3282 @*/
3283 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3284 {
3285   MatFactorInfo tinfo;
3286 
3287   PetscFunctionBegin;
3288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3289   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3290   if (info) PetscValidPointer(info, 3);
3291   PetscValidType(mat, 1);
3292   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3295   MatCheckPreallocated(mat, 1);
3296   if (!info) {
3297     PetscCall(MatFactorInfoInitialize(&tinfo));
3298     info = &tinfo;
3299   }
3300 
3301   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3302   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3303   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3304   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3305   PetscFunctionReturn(PETSC_SUCCESS);
3306 }
3307 
3308 /*@C
3309    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3310    of a symmetric matrix.
3311 
3312    Collective
3313 
3314    Input Parameters:
3315 +  fact - the factor matrix obtained with `MatGetFactor()`
3316 .  mat - the matrix
3317 .  perm - row and column permutations
3318 -  info - options for factorization, includes
3319 .vb
3320           fill - expected fill as ratio of original fill.
3321           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3322                    Run with the option -info to determine an optimal value to use
3323 .ve
3324 
3325    Level: developer
3326 
3327    Notes:
3328    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3329    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3330 
3331    Most users should employ the `KSP` interface for linear solvers
3332    instead of working directly with matrix algebra routines such as this.
3333    See, e.g., `KSPCreate()`.
3334 
3335    Developer Note:
3336    The Fortran interface is not autogenerated as the
3337    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3338 
3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3340           `MatGetOrdering()`
3341 @*/
3342 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3343 {
3344   MatFactorInfo tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3349   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3350   if (info) PetscValidPointer(info, 4);
3351   PetscValidType(fact, 1);
3352   PetscValidType(mat, 2);
3353   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3354   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3355   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3356   MatCheckPreallocated(mat, 2);
3357   if (!info) {
3358     PetscCall(MatFactorInfoInitialize(&tinfo));
3359     info = &tinfo;
3360   }
3361 
3362   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3363   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3364   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3365   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3366   PetscFunctionReturn(PETSC_SUCCESS);
3367 }
3368 
3369 /*@C
3370    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3371    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3372    `MatCholeskyFactorSymbolic()`.
3373 
3374    Collective
3375 
3376    Input Parameters:
3377 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3378 .  mat - the initial matrix that is to be factored
3379 -  info - options for factorization
3380 
3381    Level: developer
3382 
3383    Note:
3384    Most users should employ the `KSP` interface for linear solvers
3385    instead of working directly with matrix algebra routines such as this.
3386    See, e.g., `KSPCreate()`.
3387 
3388    Developer Note:
3389    The Fortran interface is not autogenerated as the
3390    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3391 
3392 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3393 @*/
3394 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3395 {
3396   MatFactorInfo tinfo;
3397 
3398   PetscFunctionBegin;
3399   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3401   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3402   PetscValidType(fact, 1);
3403   PetscValidType(mat, 2);
3404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3405   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,
3406              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3407   MatCheckPreallocated(mat, 2);
3408   if (!info) {
3409     PetscCall(MatFactorInfoInitialize(&tinfo));
3410     info = &tinfo;
3411   }
3412 
3413   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3414   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3415   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3416   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3417   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3418   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3419   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3420   PetscFunctionReturn(PETSC_SUCCESS);
3421 }
3422 
3423 /*@
3424    MatQRFactor - Performs in-place QR factorization of matrix.
3425 
3426    Collective
3427 
3428    Input Parameters:
3429 +  mat - the matrix
3430 .  col - column permutation
3431 -  info - options for factorization, includes
3432 .vb
3433           fill - expected fill as ratio of original fill.
3434           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3435                    Run with the option -info to determine an optimal value to use
3436 .ve
3437 
3438    Level: developer
3439 
3440    Notes:
3441    Most users should employ the `KSP` interface for linear solvers
3442    instead of working directly with matrix algebra routines such as this.
3443    See, e.g., `KSPCreate()`.
3444 
3445    This changes the state of the matrix to a factored matrix; it cannot be used
3446    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3447 
3448    Developer Note:
3449    The Fortran interface is not autogenerated as the
3450    interface definition cannot be generated correctly [due to MatFactorInfo]
3451 
3452 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3453           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3454 @*/
3455 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3456 {
3457   PetscFunctionBegin;
3458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3459   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3460   if (info) PetscValidPointer(info, 3);
3461   PetscValidType(mat, 1);
3462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3464   MatCheckPreallocated(mat, 1);
3465   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3466   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3467   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3468   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3469   PetscFunctionReturn(PETSC_SUCCESS);
3470 }
3471 
3472 /*@
3473    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3474    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3475 
3476    Collective
3477 
3478    Input Parameters:
3479 +  fact - the factor matrix obtained with `MatGetFactor()`
3480 .  mat - the matrix
3481 .  col - column permutation
3482 -  info - options for factorization, includes
3483 .vb
3484           fill - expected fill as ratio of original fill.
3485           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3486                    Run with the option -info to determine an optimal value to use
3487 .ve
3488 
3489    Level: developer
3490 
3491    Note:
3492    Most users should employ the `KSP` interface for linear solvers
3493    instead of working directly with matrix algebra routines such as this.
3494    See, e.g., `KSPCreate()`.
3495 
3496    Developer Note:
3497    The Fortran interface is not autogenerated as the
3498    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3499 
3500 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3501 @*/
3502 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3503 {
3504   MatFactorInfo tinfo;
3505 
3506   PetscFunctionBegin;
3507   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3509   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3510   if (info) PetscValidPointer(info, 4);
3511   PetscValidType(fact, 1);
3512   PetscValidType(mat, 2);
3513   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3514   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3515   MatCheckPreallocated(mat, 2);
3516   if (!info) {
3517     PetscCall(MatFactorInfoInitialize(&tinfo));
3518     info = &tinfo;
3519   }
3520 
3521   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3522   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3523   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3524   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3525   PetscFunctionReturn(PETSC_SUCCESS);
3526 }
3527 
3528 /*@
3529    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3530    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3531 
3532    Collective
3533 
3534    Input Parameters:
3535 +  fact - the factor matrix obtained with `MatGetFactor()`
3536 .  mat - the matrix
3537 -  info - options for factorization
3538 
3539    Level: developer
3540 
3541    Notes:
3542    See `MatQRFactor()` for in-place factorization.
3543 
3544    Most users should employ the `KSP` interface for linear solvers
3545    instead of working directly with matrix algebra routines such as this.
3546    See, e.g., `KSPCreate()`.
3547 
3548    Developer Note:
3549    The Fortran interface is not autogenerated as the
3550    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3551 
3552 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3553 @*/
3554 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3555 {
3556   MatFactorInfo tinfo;
3557 
3558   PetscFunctionBegin;
3559   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3561   PetscValidType(fact, 1);
3562   PetscValidType(mat, 2);
3563   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3564   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,
3565              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3566 
3567   MatCheckPreallocated(mat, 2);
3568   if (!info) {
3569     PetscCall(MatFactorInfoInitialize(&tinfo));
3570     info = &tinfo;
3571   }
3572 
3573   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3574   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3575   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3576   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3577   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3578   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3579   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3580   PetscFunctionReturn(PETSC_SUCCESS);
3581 }
3582 
3583 /*@
3584    MatSolve - Solves A x = b, given a factored matrix.
3585 
3586    Neighbor-wise Collective
3587 
3588    Input Parameters:
3589 +  mat - the factored matrix
3590 -  b - the right-hand-side vector
3591 
3592    Output Parameter:
3593 .  x - the result vector
3594 
3595    Level: developer
3596 
3597    Notes:
3598    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3599    call `MatSolve`(A,x,x).
3600 
3601    Most users should employ the `KSP` interface for linear solvers
3602    instead of working directly with matrix algebra routines such as this.
3603    See, e.g., `KSPCreate()`.
3604 
3605 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3606 @*/
3607 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3608 {
3609   PetscFunctionBegin;
3610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3611   PetscValidType(mat, 1);
3612   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3613   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3614   PetscCheckSameComm(mat, 1, b, 2);
3615   PetscCheckSameComm(mat, 1, x, 3);
3616   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3617   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);
3618   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);
3619   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);
3620   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3621   MatCheckPreallocated(mat, 1);
3622 
3623   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3624   if (mat->factorerrortype) {
3625     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3626     PetscCall(VecSetInf(x));
3627   } else PetscUseTypeMethod(mat, solve, b, x);
3628   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3629   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3630   PetscFunctionReturn(PETSC_SUCCESS);
3631 }
3632 
3633 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3634 {
3635   Vec      b, x;
3636   PetscInt N, i;
3637   PetscErrorCode (*f)(Mat, Vec, Vec);
3638   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3639 
3640   PetscFunctionBegin;
3641   if (A->factorerrortype) {
3642     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3643     PetscCall(MatSetInf(X));
3644     PetscFunctionReturn(PETSC_SUCCESS);
3645   }
3646   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3647   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3648   PetscCall(MatBoundToCPU(A, &Abound));
3649   if (!Abound) {
3650     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3651     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3652   }
3653 #if PetscDefined(HAVE_CUDA)
3654   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3655   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3656 #elif PetscDefined(HAVE_HIP)
3657   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3658   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3659 #endif
3660   PetscCall(MatGetSize(B, NULL, &N));
3661   for (i = 0; i < N; i++) {
3662     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3663     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3664     PetscCall((*f)(A, b, x));
3665     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3666     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3667   }
3668   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3669   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3670   PetscFunctionReturn(PETSC_SUCCESS);
3671 }
3672 
3673 /*@
3674    MatMatSolve - Solves A X = B, given a factored matrix.
3675 
3676    Neighbor-wise Collective
3677 
3678    Input Parameters:
3679 +  A - the factored matrix
3680 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3681 
3682    Output Parameter:
3683 .  X - the result matrix (dense matrix)
3684 
3685    Level: developer
3686 
3687    Note:
3688    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3689    otherwise, `B` and `X` cannot be the same.
3690 
3691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3692 @*/
3693 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3694 {
3695   PetscFunctionBegin;
3696   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3697   PetscValidType(A, 1);
3698   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3699   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3700   PetscCheckSameComm(A, 1, B, 2);
3701   PetscCheckSameComm(A, 1, X, 3);
3702   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);
3703   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);
3704   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");
3705   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3706   MatCheckPreallocated(A, 1);
3707 
3708   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3709   if (!A->ops->matsolve) {
3710     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3711     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3712   } else PetscUseTypeMethod(A, matsolve, B, X);
3713   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3714   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3715   PetscFunctionReturn(PETSC_SUCCESS);
3716 }
3717 
3718 /*@
3719    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3720 
3721    Neighbor-wise Collective
3722 
3723    Input Parameters:
3724 +  A - the factored matrix
3725 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3726 
3727    Output Parameter:
3728 .  X - the result matrix (dense matrix)
3729 
3730    Level: developer
3731 
3732    Note:
3733    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3734    call `MatMatSolveTranspose`(A,X,X).
3735 
3736 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3737 @*/
3738 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3739 {
3740   PetscFunctionBegin;
3741   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3742   PetscValidType(A, 1);
3743   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3744   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3745   PetscCheckSameComm(A, 1, B, 2);
3746   PetscCheckSameComm(A, 1, X, 3);
3747   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3748   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);
3749   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);
3750   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);
3751   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");
3752   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3753   MatCheckPreallocated(A, 1);
3754 
3755   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3756   if (!A->ops->matsolvetranspose) {
3757     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3758     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3759   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3760   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3761   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3762   PetscFunctionReturn(PETSC_SUCCESS);
3763 }
3764 
3765 /*@
3766    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3767 
3768    Neighbor-wise Collective
3769 
3770    Input Parameters:
3771 +  A - the factored matrix
3772 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3773 
3774    Output Parameter:
3775 .  X - the result matrix (dense matrix)
3776 
3777    Level: developer
3778 
3779    Note:
3780    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
3781    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3782 
3783 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3784 @*/
3785 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3786 {
3787   PetscFunctionBegin;
3788   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3789   PetscValidType(A, 1);
3790   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3791   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3792   PetscCheckSameComm(A, 1, Bt, 2);
3793   PetscCheckSameComm(A, 1, X, 3);
3794 
3795   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3796   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);
3797   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);
3798   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");
3799   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3800   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3801   MatCheckPreallocated(A, 1);
3802 
3803   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3804   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3805   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3806   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3807   PetscFunctionReturn(PETSC_SUCCESS);
3808 }
3809 
3810 /*@
3811    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3812                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3813 
3814    Neighbor-wise Collective
3815 
3816    Input Parameters:
3817 +  mat - the factored matrix
3818 -  b - the right-hand-side vector
3819 
3820    Output Parameter:
3821 .  x - the result vector
3822 
3823    Level: developer
3824 
3825    Notes:
3826    `MatSolve()` should be used for most applications, as it performs
3827    a forward solve followed by a backward solve.
3828 
3829    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3830    call `MatForwardSolve`(A,x,x).
3831 
3832    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3833    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3834    `MatForwardSolve()` solves U^T*D y = b, and
3835    `MatBackwardSolve()` solves U x = y.
3836    Thus they do not provide a symmetric preconditioner.
3837 
3838 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3839 @*/
3840 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3841 {
3842   PetscFunctionBegin;
3843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3844   PetscValidType(mat, 1);
3845   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3846   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3847   PetscCheckSameComm(mat, 1, b, 2);
3848   PetscCheckSameComm(mat, 1, x, 3);
3849   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3850   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);
3851   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);
3852   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);
3853   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3854   MatCheckPreallocated(mat, 1);
3855 
3856   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3857   PetscUseTypeMethod(mat, forwardsolve, b, x);
3858   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3859   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3860   PetscFunctionReturn(PETSC_SUCCESS);
3861 }
3862 
3863 /*@
3864    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3865                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3866 
3867    Neighbor-wise Collective
3868 
3869    Input Parameters:
3870 +  mat - the factored matrix
3871 -  b - the right-hand-side vector
3872 
3873    Output Parameter:
3874 .  x - the result vector
3875 
3876    Level: developer
3877 
3878    Notes:
3879    `MatSolve()` should be used for most applications, as it performs
3880    a forward solve followed by a backward solve.
3881 
3882    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3883    call `MatBackwardSolve`(A,x,x).
3884 
3885    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3886    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3887    `MatForwardSolve()` solves U^T*D y = b, and
3888    `MatBackwardSolve()` solves U x = y.
3889    Thus they do not provide a symmetric preconditioner.
3890 
3891 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3892 @*/
3893 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3894 {
3895   PetscFunctionBegin;
3896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3897   PetscValidType(mat, 1);
3898   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3899   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3900   PetscCheckSameComm(mat, 1, b, 2);
3901   PetscCheckSameComm(mat, 1, x, 3);
3902   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3903   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);
3904   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);
3905   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);
3906   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3907   MatCheckPreallocated(mat, 1);
3908 
3909   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3910   PetscUseTypeMethod(mat, backwardsolve, b, x);
3911   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3912   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3913   PetscFunctionReturn(PETSC_SUCCESS);
3914 }
3915 
3916 /*@
3917    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3918 
3919    Neighbor-wise Collective
3920 
3921    Input Parameters:
3922 +  mat - the factored matrix
3923 .  b - the right-hand-side vector
3924 -  y - the vector to be added to
3925 
3926    Output Parameter:
3927 .  x - the result vector
3928 
3929    Level: developer
3930 
3931    Note:
3932    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3933    call `MatSolveAdd`(A,x,y,x).
3934 
3935 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3936 @*/
3937 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3938 {
3939   PetscScalar one = 1.0;
3940   Vec         tmp;
3941 
3942   PetscFunctionBegin;
3943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3944   PetscValidType(mat, 1);
3945   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3946   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3947   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3948   PetscCheckSameComm(mat, 1, b, 2);
3949   PetscCheckSameComm(mat, 1, y, 3);
3950   PetscCheckSameComm(mat, 1, x, 4);
3951   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3952   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);
3953   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);
3954   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);
3955   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);
3956   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);
3957   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3958   MatCheckPreallocated(mat, 1);
3959 
3960   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3961   if (mat->factorerrortype) {
3962     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3963     PetscCall(VecSetInf(x));
3964   } else if (mat->ops->solveadd) {
3965     PetscUseTypeMethod(mat, solveadd, b, y, x);
3966   } else {
3967     /* do the solve then the add manually */
3968     if (x != y) {
3969       PetscCall(MatSolve(mat, b, x));
3970       PetscCall(VecAXPY(x, one, y));
3971     } else {
3972       PetscCall(VecDuplicate(x, &tmp));
3973       PetscCall(VecCopy(x, tmp));
3974       PetscCall(MatSolve(mat, b, x));
3975       PetscCall(VecAXPY(x, one, tmp));
3976       PetscCall(VecDestroy(&tmp));
3977     }
3978   }
3979   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3980   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3981   PetscFunctionReturn(PETSC_SUCCESS);
3982 }
3983 
3984 /*@
3985    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3986 
3987    Neighbor-wise Collective
3988 
3989    Input Parameters:
3990 +  mat - the factored matrix
3991 -  b - the right-hand-side vector
3992 
3993    Output Parameter:
3994 .  x - the result vector
3995 
3996    Level: developer
3997 
3998    Notes:
3999    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4000    call `MatSolveTranspose`(A,x,x).
4001 
4002    Most users should employ the `KSP` interface for linear solvers
4003    instead of working directly with matrix algebra routines such as this.
4004    See, e.g., `KSPCreate()`.
4005 
4006 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4007 @*/
4008 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4009 {
4010   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4011 
4012   PetscFunctionBegin;
4013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4014   PetscValidType(mat, 1);
4015   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4016   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4017   PetscCheckSameComm(mat, 1, b, 2);
4018   PetscCheckSameComm(mat, 1, x, 3);
4019   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4020   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);
4021   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);
4022   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4023   MatCheckPreallocated(mat, 1);
4024   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4025   if (mat->factorerrortype) {
4026     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4027     PetscCall(VecSetInf(x));
4028   } else {
4029     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4030     PetscCall((*f)(mat, b, x));
4031   }
4032   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4033   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4034   PetscFunctionReturn(PETSC_SUCCESS);
4035 }
4036 
4037 /*@
4038    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4039                       factored matrix.
4040 
4041    Neighbor-wise Collective
4042 
4043    Input Parameters:
4044 +  mat - the factored matrix
4045 .  b - the right-hand-side vector
4046 -  y - the vector to be added to
4047 
4048    Output Parameter:
4049 .  x - the result vector
4050 
4051    Level: developer
4052 
4053    Note:
4054    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4055    call `MatSolveTransposeAdd`(A,x,y,x).
4056 
4057 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4058 @*/
4059 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4060 {
4061   PetscScalar one = 1.0;
4062   Vec         tmp;
4063   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4064 
4065   PetscFunctionBegin;
4066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4067   PetscValidType(mat, 1);
4068   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4069   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4070   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4071   PetscCheckSameComm(mat, 1, b, 2);
4072   PetscCheckSameComm(mat, 1, y, 3);
4073   PetscCheckSameComm(mat, 1, x, 4);
4074   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4075   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);
4076   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);
4077   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);
4078   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);
4079   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4080   MatCheckPreallocated(mat, 1);
4081 
4082   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4083   if (mat->factorerrortype) {
4084     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4085     PetscCall(VecSetInf(x));
4086   } else if (f) {
4087     PetscCall((*f)(mat, b, y, x));
4088   } else {
4089     /* do the solve then the add manually */
4090     if (x != y) {
4091       PetscCall(MatSolveTranspose(mat, b, x));
4092       PetscCall(VecAXPY(x, one, y));
4093     } else {
4094       PetscCall(VecDuplicate(x, &tmp));
4095       PetscCall(VecCopy(x, tmp));
4096       PetscCall(MatSolveTranspose(mat, b, x));
4097       PetscCall(VecAXPY(x, one, tmp));
4098       PetscCall(VecDestroy(&tmp));
4099     }
4100   }
4101   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4102   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4103   PetscFunctionReturn(PETSC_SUCCESS);
4104 }
4105 
4106 /*@
4107    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4108 
4109    Neighbor-wise Collective
4110 
4111    Input Parameters:
4112 +  mat - the matrix
4113 .  b - the right hand side
4114 .  omega - the relaxation factor
4115 .  flag - flag indicating the type of SOR (see below)
4116 .  shift -  diagonal shift
4117 .  its - the number of iterations
4118 -  lits - the number of local iterations
4119 
4120    Output Parameter:
4121 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4122 
4123    SOR Flags:
4124 +     `SOR_FORWARD_SWEEP` - forward SOR
4125 .     `SOR_BACKWARD_SWEEP` - backward SOR
4126 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4127 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4128 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4129 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4130 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4131 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4132          upper/lower triangular part of matrix to
4133          vector (with omega)
4134 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4135 
4136    Level: developer
4137 
4138    Notes:
4139    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4140    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4141    on each processor.
4142 
4143    Application programmers will not generally use `MatSOR()` directly,
4144    but instead will employ the `KSP`/`PC` interface.
4145 
4146    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4147 
4148    Most users should employ the `KSP` interface for linear solvers
4149    instead of working directly with matrix algebra routines such as this.
4150    See, e.g., `KSPCreate()`.
4151 
4152    Vectors `x` and `b` CANNOT be the same
4153 
4154    The flags are implemented as bitwise inclusive or operations.
4155    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4156    to specify a zero initial guess for SSOR.
4157 
4158    Developer Note:
4159    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4160 
4161 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4162 @*/
4163 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4164 {
4165   PetscFunctionBegin;
4166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4167   PetscValidType(mat, 1);
4168   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4169   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4170   PetscCheckSameComm(mat, 1, b, 2);
4171   PetscCheckSameComm(mat, 1, x, 8);
4172   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4173   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4174   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);
4175   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);
4176   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);
4177   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4178   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4179   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4180 
4181   MatCheckPreallocated(mat, 1);
4182   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4183   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4184   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4185   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4186   PetscFunctionReturn(PETSC_SUCCESS);
4187 }
4188 
4189 /*
4190       Default matrix copy routine.
4191 */
4192 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4193 {
4194   PetscInt           i, rstart = 0, rend = 0, nz;
4195   const PetscInt    *cwork;
4196   const PetscScalar *vwork;
4197 
4198   PetscFunctionBegin;
4199   if (B->assembled) PetscCall(MatZeroEntries(B));
4200   if (str == SAME_NONZERO_PATTERN) {
4201     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4202     for (i = rstart; i < rend; i++) {
4203       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4204       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4205       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4206     }
4207   } else {
4208     PetscCall(MatAYPX(B, 0.0, A, str));
4209   }
4210   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4211   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4212   PetscFunctionReturn(PETSC_SUCCESS);
4213 }
4214 
4215 /*@
4216    MatCopy - Copies a matrix to another matrix.
4217 
4218    Collective
4219 
4220    Input Parameters:
4221 +  A - the matrix
4222 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4223 
4224    Output Parameter:
4225 .  B - where the copy is put
4226 
4227    Level: intermediate
4228 
4229    Notes:
4230    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4231 
4232    `MatCopy()` copies the matrix entries of a matrix to another existing
4233    matrix (after first zeroing the second matrix).  A related routine is
4234    `MatConvert()`, which first creates a new matrix and then copies the data.
4235 
4236 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4237 @*/
4238 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4239 {
4240   PetscInt i;
4241 
4242   PetscFunctionBegin;
4243   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4244   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4245   PetscValidType(A, 1);
4246   PetscValidType(B, 2);
4247   PetscCheckSameComm(A, 1, B, 2);
4248   MatCheckPreallocated(B, 2);
4249   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4250   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4251   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,
4252              A->cmap->N, B->cmap->N);
4253   MatCheckPreallocated(A, 1);
4254   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4255 
4256   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4257   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4258   else PetscCall(MatCopy_Basic(A, B, str));
4259 
4260   B->stencil.dim = A->stencil.dim;
4261   B->stencil.noc = A->stencil.noc;
4262   for (i = 0; i <= A->stencil.dim; i++) {
4263     B->stencil.dims[i]   = A->stencil.dims[i];
4264     B->stencil.starts[i] = A->stencil.starts[i];
4265   }
4266 
4267   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4268   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4269   PetscFunctionReturn(PETSC_SUCCESS);
4270 }
4271 
4272 /*@C
4273    MatConvert - Converts a matrix to another matrix, either of the same
4274    or different type.
4275 
4276    Collective
4277 
4278    Input Parameters:
4279 +  mat - the matrix
4280 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4281    same type as the original matrix.
4282 -  reuse - denotes if the destination matrix is to be created or reused.
4283    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
4284    `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).
4285 
4286    Output Parameter:
4287 .  M - pointer to place new matrix
4288 
4289    Level: intermediate
4290 
4291    Notes:
4292    `MatConvert()` first creates a new matrix and then copies the data from
4293    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4294    entries of one matrix to another already existing matrix context.
4295 
4296    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4297    the MPI communicator of the generated matrix is always the same as the communicator
4298    of the input matrix.
4299 
4300 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4301 @*/
4302 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4303 {
4304   PetscBool  sametype, issame, flg;
4305   PetscBool3 issymmetric, ishermitian;
4306   char       convname[256], mtype[256];
4307   Mat        B;
4308 
4309   PetscFunctionBegin;
4310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4311   PetscValidType(mat, 1);
4312   PetscValidPointer(M, 4);
4313   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4314   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4315   MatCheckPreallocated(mat, 1);
4316 
4317   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4318   if (flg) newtype = mtype;
4319 
4320   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4321   PetscCall(PetscStrcmp(newtype, "same", &issame));
4322   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4323   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");
4324 
4325   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4326     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4327     PetscFunctionReturn(PETSC_SUCCESS);
4328   }
4329 
4330   /* Cache Mat options because some converters use MatHeaderReplace  */
4331   issymmetric = mat->symmetric;
4332   ishermitian = mat->hermitian;
4333 
4334   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4335     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4336     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4337   } else {
4338     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4339     const char *prefix[3]                                 = {"seq", "mpi", ""};
4340     PetscInt    i;
4341     /*
4342        Order of precedence:
4343        0) See if newtype is a superclass of the current matrix.
4344        1) See if a specialized converter is known to the current matrix.
4345        2) See if a specialized converter is known to the desired matrix class.
4346        3) See if a good general converter is registered for the desired class
4347           (as of 6/27/03 only MATMPIADJ falls into this category).
4348        4) See if a good general converter is known for the current matrix.
4349        5) Use a really basic converter.
4350     */
4351 
4352     /* 0) See if newtype is a superclass of the current matrix.
4353           i.e mat is mpiaij and newtype is aij */
4354     for (i = 0; i < 2; i++) {
4355       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4357       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4358       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4359       if (flg) {
4360         if (reuse == MAT_INPLACE_MATRIX) {
4361           PetscCall(PetscInfo(mat, "Early return\n"));
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4364           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4365           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4368           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4369           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         }
4372       }
4373     }
4374     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4375     for (i = 0; i < 3; i++) {
4376       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4381       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4382       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4383       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4384       if (conv) goto foundconv;
4385     }
4386 
4387     /* 2)  See if a specialized converter is known to the desired matrix class. */
4388     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4389     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4390     PetscCall(MatSetType(B, newtype));
4391     for (i = 0; i < 3; i++) {
4392       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4396       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4397       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4398       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4399       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4400       if (conv) {
4401         PetscCall(MatDestroy(&B));
4402         goto foundconv;
4403       }
4404     }
4405 
4406     /* 3) See if a good general converter is registered for the desired class */
4407     conv = B->ops->convertfrom;
4408     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4409     PetscCall(MatDestroy(&B));
4410     if (conv) goto foundconv;
4411 
4412     /* 4) See if a good general converter is known for the current matrix */
4413     if (mat->ops->convert) conv = mat->ops->convert;
4414     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4415     if (conv) goto foundconv;
4416 
4417     /* 5) Use a really basic converter. */
4418     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4419     conv = MatConvert_Basic;
4420 
4421   foundconv:
4422     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4423     PetscCall((*conv)(mat, newtype, reuse, M));
4424     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4425       /* the block sizes must be same if the mappings are copied over */
4426       (*M)->rmap->bs = mat->rmap->bs;
4427       (*M)->cmap->bs = mat->cmap->bs;
4428       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4429       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4430       (*M)->rmap->mapping = mat->rmap->mapping;
4431       (*M)->cmap->mapping = mat->cmap->mapping;
4432     }
4433     (*M)->stencil.dim = mat->stencil.dim;
4434     (*M)->stencil.noc = mat->stencil.noc;
4435     for (i = 0; i <= mat->stencil.dim; i++) {
4436       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4437       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4438     }
4439     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4440   }
4441   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4442 
4443   /* Copy Mat options */
4444   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4445   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4446   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4447   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4448   PetscFunctionReturn(PETSC_SUCCESS);
4449 }
4450 
4451 /*@C
4452    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4453 
4454    Not Collective
4455 
4456    Input Parameter:
4457 .  mat - the matrix, must be a factored matrix
4458 
4459    Output Parameter:
4460 .   type - the string name of the package (do not free this string)
4461 
4462    Level: intermediate
4463 
4464    Fortran Note:
4465    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4466 
4467 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4468 @*/
4469 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4470 {
4471   PetscErrorCode (*conv)(Mat, MatSolverType *);
4472 
4473   PetscFunctionBegin;
4474   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4475   PetscValidType(mat, 1);
4476   PetscValidPointer(type, 2);
4477   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4478   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4479   if (conv) PetscCall((*conv)(mat, type));
4480   else *type = MATSOLVERPETSC;
4481   PetscFunctionReturn(PETSC_SUCCESS);
4482 }
4483 
4484 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4485 struct _MatSolverTypeForSpecifcType {
4486   MatType mtype;
4487   /* no entry for MAT_FACTOR_NONE */
4488   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4489   MatSolverTypeForSpecifcType next;
4490 };
4491 
4492 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4493 struct _MatSolverTypeHolder {
4494   char                       *name;
4495   MatSolverTypeForSpecifcType handlers;
4496   MatSolverTypeHolder         next;
4497 };
4498 
4499 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4500 
4501 /*@C
4502    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4503 
4504    Input Parameters:
4505 +    package - name of the package, for example petsc or superlu
4506 .    mtype - the matrix type that works with this package
4507 .    ftype - the type of factorization supported by the package
4508 -    createfactor - routine that will create the factored matrix ready to be used
4509 
4510     Level: developer
4511 
4512 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4513 @*/
4514 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4515 {
4516   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4517   PetscBool                   flg;
4518   MatSolverTypeForSpecifcType inext, iprev = NULL;
4519 
4520   PetscFunctionBegin;
4521   PetscCall(MatInitializePackage());
4522   if (!next) {
4523     PetscCall(PetscNew(&MatSolverTypeHolders));
4524     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4525     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4526     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4527     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4528     PetscFunctionReturn(PETSC_SUCCESS);
4529   }
4530   while (next) {
4531     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4532     if (flg) {
4533       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4534       inext = next->handlers;
4535       while (inext) {
4536         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4537         if (flg) {
4538           inext->createfactor[(int)ftype - 1] = createfactor;
4539           PetscFunctionReturn(PETSC_SUCCESS);
4540         }
4541         iprev = inext;
4542         inext = inext->next;
4543       }
4544       PetscCall(PetscNew(&iprev->next));
4545       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4546       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4547       PetscFunctionReturn(PETSC_SUCCESS);
4548     }
4549     prev = next;
4550     next = next->next;
4551   }
4552   PetscCall(PetscNew(&prev->next));
4553   PetscCall(PetscStrallocpy(package, &prev->next->name));
4554   PetscCall(PetscNew(&prev->next->handlers));
4555   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4556   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4557   PetscFunctionReturn(PETSC_SUCCESS);
4558 }
4559 
4560 /*@C
4561    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4562 
4563    Input Parameters:
4564 +    type - name of the package, for example petsc or superlu
4565 .    ftype - the type of factorization supported by the type
4566 -    mtype - the matrix type that works with this type
4567 
4568    Output Parameters:
4569 +   foundtype - `PETSC_TRUE` if the type was registered
4570 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4571 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4572 
4573     Level: developer
4574 
4575 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4576 @*/
4577 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4578 {
4579   MatSolverTypeHolder         next = MatSolverTypeHolders;
4580   PetscBool                   flg;
4581   MatSolverTypeForSpecifcType inext;
4582 
4583   PetscFunctionBegin;
4584   if (foundtype) *foundtype = PETSC_FALSE;
4585   if (foundmtype) *foundmtype = PETSC_FALSE;
4586   if (createfactor) *createfactor = NULL;
4587 
4588   if (type) {
4589     while (next) {
4590       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4591       if (flg) {
4592         if (foundtype) *foundtype = PETSC_TRUE;
4593         inext = next->handlers;
4594         while (inext) {
4595           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4596           if (flg) {
4597             if (foundmtype) *foundmtype = PETSC_TRUE;
4598             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4599             PetscFunctionReturn(PETSC_SUCCESS);
4600           }
4601           inext = inext->next;
4602         }
4603       }
4604       next = next->next;
4605     }
4606   } else {
4607     while (next) {
4608       inext = next->handlers;
4609       while (inext) {
4610         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4611         if (flg && inext->createfactor[(int)ftype - 1]) {
4612           if (foundtype) *foundtype = PETSC_TRUE;
4613           if (foundmtype) *foundmtype = PETSC_TRUE;
4614           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4615           PetscFunctionReturn(PETSC_SUCCESS);
4616         }
4617         inext = inext->next;
4618       }
4619       next = next->next;
4620     }
4621     /* try with base classes inext->mtype */
4622     next = MatSolverTypeHolders;
4623     while (next) {
4624       inext = next->handlers;
4625       while (inext) {
4626         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4627         if (flg && inext->createfactor[(int)ftype - 1]) {
4628           if (foundtype) *foundtype = PETSC_TRUE;
4629           if (foundmtype) *foundmtype = PETSC_TRUE;
4630           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4631           PetscFunctionReturn(PETSC_SUCCESS);
4632         }
4633         inext = inext->next;
4634       }
4635       next = next->next;
4636     }
4637   }
4638   PetscFunctionReturn(PETSC_SUCCESS);
4639 }
4640 
4641 PetscErrorCode MatSolverTypeDestroy(void)
4642 {
4643   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4644   MatSolverTypeForSpecifcType inext, iprev;
4645 
4646   PetscFunctionBegin;
4647   while (next) {
4648     PetscCall(PetscFree(next->name));
4649     inext = next->handlers;
4650     while (inext) {
4651       PetscCall(PetscFree(inext->mtype));
4652       iprev = inext;
4653       inext = inext->next;
4654       PetscCall(PetscFree(iprev));
4655     }
4656     prev = next;
4657     next = next->next;
4658     PetscCall(PetscFree(prev));
4659   }
4660   MatSolverTypeHolders = NULL;
4661   PetscFunctionReturn(PETSC_SUCCESS);
4662 }
4663 
4664 /*@C
4665    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4666 
4667    Logically Collective
4668 
4669    Input Parameter:
4670 .  mat - the matrix
4671 
4672    Output Parameter:
4673 .  flg - `PETSC_TRUE` if uses the ordering
4674 
4675    Level: developer
4676 
4677    Note:
4678    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4679    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4680 
4681 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4682 @*/
4683 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4684 {
4685   PetscFunctionBegin;
4686   *flg = mat->canuseordering;
4687   PetscFunctionReturn(PETSC_SUCCESS);
4688 }
4689 
4690 /*@C
4691    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4692 
4693    Logically Collective
4694 
4695    Input Parameters:
4696 +  mat - the matrix obtained with `MatGetFactor()`
4697 -  ftype - the factorization type to be used
4698 
4699    Output Parameter:
4700 .  otype - the preferred ordering type
4701 
4702    Level: developer
4703 
4704 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4705 @*/
4706 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4707 {
4708   PetscFunctionBegin;
4709   *otype = mat->preferredordering[ftype];
4710   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4711   PetscFunctionReturn(PETSC_SUCCESS);
4712 }
4713 
4714 /*@C
4715    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4716 
4717    Collective
4718 
4719    Input Parameters:
4720 +  mat - the matrix
4721 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4722 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4723 
4724    Output Parameter:
4725 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4726 
4727    Options Database Key:
4728 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4729                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4730 
4731    Level: intermediate
4732 
4733    Notes:
4734      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4735      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4736 
4737      Users usually access the factorization solvers via `KSP`
4738 
4739       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4740      such as pastix, superlu, mumps etc.
4741 
4742       PETSc must have been ./configure to use the external solver, using the option --download-package
4743 
4744       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4745       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4746       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4747 
4748    Developer Note:
4749       This should actually be called `MatCreateFactor()` since it creates a new factor object
4750 
4751 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4752           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4753 @*/
4754 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4755 {
4756   PetscBool foundtype, foundmtype;
4757   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4758 
4759   PetscFunctionBegin;
4760   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4761   PetscValidType(mat, 1);
4762 
4763   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4764   MatCheckPreallocated(mat, 1);
4765 
4766   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4767   if (!foundtype) {
4768     if (type) {
4769       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],
4770               ((PetscObject)mat)->type_name, type);
4771     } else {
4772       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);
4773     }
4774   }
4775   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4776   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);
4777 
4778   PetscCall((*conv)(mat, ftype, f));
4779   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4780   PetscFunctionReturn(PETSC_SUCCESS);
4781 }
4782 
4783 /*@C
4784    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4785 
4786    Not Collective
4787 
4788    Input Parameters:
4789 +  mat - the matrix
4790 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4791 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4792 
4793    Output Parameter:
4794 .    flg - PETSC_TRUE if the factorization is available
4795 
4796    Level: intermediate
4797 
4798    Notes:
4799       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4800      such as pastix, superlu, mumps etc.
4801 
4802       PETSc must have been ./configure to use the external solver, using the option --download-package
4803 
4804    Developer Note:
4805       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4806 
4807 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4808           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4809 @*/
4810 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4811 {
4812   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4813 
4814   PetscFunctionBegin;
4815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4816   PetscValidType(mat, 1);
4817   PetscValidBoolPointer(flg, 4);
4818 
4819   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4820   MatCheckPreallocated(mat, 1);
4821 
4822   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4823   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4824   PetscFunctionReturn(PETSC_SUCCESS);
4825 }
4826 
4827 /*@
4828    MatDuplicate - Duplicates a matrix including the non-zero structure.
4829 
4830    Collective
4831 
4832    Input Parameters:
4833 +  mat - the matrix
4834 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4835         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4836 
4837    Output Parameter:
4838 .  M - pointer to place new matrix
4839 
4840    Level: intermediate
4841 
4842    Notes:
4843     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4844 
4845     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.
4846 
4847     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
4848     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4849     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4850 
4851 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4852 @*/
4853 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4854 {
4855   Mat         B;
4856   VecType     vtype;
4857   PetscInt    i;
4858   PetscObject dm, container_h, container_d;
4859   void (*viewf)(void);
4860 
4861   PetscFunctionBegin;
4862   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4863   PetscValidType(mat, 1);
4864   PetscValidPointer(M, 3);
4865   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4866   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4867   MatCheckPreallocated(mat, 1);
4868 
4869   *M = NULL;
4870   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4871   PetscUseTypeMethod(mat, duplicate, op, M);
4872   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4873   B = *M;
4874 
4875   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4876   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4877   PetscCall(MatGetVecType(mat, &vtype));
4878   PetscCall(MatSetVecType(B, vtype));
4879 
4880   B->stencil.dim = mat->stencil.dim;
4881   B->stencil.noc = mat->stencil.noc;
4882   for (i = 0; i <= mat->stencil.dim; i++) {
4883     B->stencil.dims[i]   = mat->stencil.dims[i];
4884     B->stencil.starts[i] = mat->stencil.starts[i];
4885   }
4886 
4887   B->nooffproczerorows = mat->nooffproczerorows;
4888   B->nooffprocentries  = mat->nooffprocentries;
4889 
4890   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4891   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4892   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4893   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4894   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4895   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4896   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4897   PetscFunctionReturn(PETSC_SUCCESS);
4898 }
4899 
4900 /*@
4901    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4902 
4903    Logically Collective
4904 
4905    Input Parameter:
4906 .  mat - the matrix
4907 
4908    Output Parameter:
4909 .  v - the diagonal of the matrix
4910 
4911    Level: intermediate
4912 
4913    Note:
4914    Currently only correct in parallel for square matrices.
4915 
4916 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4917 @*/
4918 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4919 {
4920   PetscFunctionBegin;
4921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4922   PetscValidType(mat, 1);
4923   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4924   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4925   MatCheckPreallocated(mat, 1);
4926 
4927   PetscUseTypeMethod(mat, getdiagonal, v);
4928   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4929   PetscFunctionReturn(PETSC_SUCCESS);
4930 }
4931 
4932 /*@C
4933    MatGetRowMin - Gets the minimum value (of the real part) of each
4934         row of the matrix
4935 
4936    Logically Collective
4937 
4938    Input Parameter:
4939 .  mat - the matrix
4940 
4941    Output Parameters:
4942 +  v - the vector for storing the maximums
4943 -  idx - the indices of the column found for each row (optional)
4944 
4945    Level: intermediate
4946 
4947    Note:
4948     The result of this call are the same as if one converted the matrix to dense format
4949       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4950 
4951     This code is only implemented for a couple of matrix formats.
4952 
4953 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4954           `MatGetRowMax()`
4955 @*/
4956 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4957 {
4958   PetscFunctionBegin;
4959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4960   PetscValidType(mat, 1);
4961   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4962   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4963 
4964   if (!mat->cmap->N) {
4965     PetscCall(VecSet(v, PETSC_MAX_REAL));
4966     if (idx) {
4967       PetscInt i, m = mat->rmap->n;
4968       for (i = 0; i < m; i++) idx[i] = -1;
4969     }
4970   } else {
4971     MatCheckPreallocated(mat, 1);
4972   }
4973   PetscUseTypeMethod(mat, getrowmin, v, idx);
4974   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4975   PetscFunctionReturn(PETSC_SUCCESS);
4976 }
4977 
4978 /*@C
4979    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4980         row of the matrix
4981 
4982    Logically Collective
4983 
4984    Input Parameter:
4985 .  mat - the matrix
4986 
4987    Output Parameters:
4988 +  v - the vector for storing the minimums
4989 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4990 
4991    Level: intermediate
4992 
4993    Notes:
4994     if a row is completely empty or has only 0.0 values then the idx[] value for that
4995     row is 0 (the first column).
4996 
4997     This code is only implemented for a couple of matrix formats.
4998 
4999 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5000 @*/
5001 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5002 {
5003   PetscFunctionBegin;
5004   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5005   PetscValidType(mat, 1);
5006   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5007   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5008   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5009 
5010   if (!mat->cmap->N) {
5011     PetscCall(VecSet(v, 0.0));
5012     if (idx) {
5013       PetscInt i, m = mat->rmap->n;
5014       for (i = 0; i < m; i++) idx[i] = -1;
5015     }
5016   } else {
5017     MatCheckPreallocated(mat, 1);
5018     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5019     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5020   }
5021   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5022   PetscFunctionReturn(PETSC_SUCCESS);
5023 }
5024 
5025 /*@C
5026    MatGetRowMax - Gets the maximum value (of the real part) of each
5027         row of the matrix
5028 
5029    Logically Collective
5030 
5031    Input Parameter:
5032 .  mat - the matrix
5033 
5034    Output Parameters:
5035 +  v - the vector for storing the maximums
5036 -  idx - the indices of the column found for each row (optional)
5037 
5038    Level: intermediate
5039 
5040    Notes:
5041     The result of this call are the same as if one converted the matrix to dense format
5042       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5043 
5044     This code is only implemented for a couple of matrix formats.
5045 
5046 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5047 @*/
5048 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5049 {
5050   PetscFunctionBegin;
5051   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5052   PetscValidType(mat, 1);
5053   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5054   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5055 
5056   if (!mat->cmap->N) {
5057     PetscCall(VecSet(v, PETSC_MIN_REAL));
5058     if (idx) {
5059       PetscInt i, m = mat->rmap->n;
5060       for (i = 0; i < m; i++) idx[i] = -1;
5061     }
5062   } else {
5063     MatCheckPreallocated(mat, 1);
5064     PetscUseTypeMethod(mat, getrowmax, v, idx);
5065   }
5066   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5067   PetscFunctionReturn(PETSC_SUCCESS);
5068 }
5069 
5070 /*@C
5071    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5072         row of the matrix
5073 
5074    Logically Collective
5075 
5076    Input Parameter:
5077 .  mat - the matrix
5078 
5079    Output Parameters:
5080 +  v - the vector for storing the maximums
5081 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5082 
5083    Level: intermediate
5084 
5085    Notes:
5086     if a row is completely empty or has only 0.0 values then the idx[] value for that
5087     row is 0 (the first column).
5088 
5089     This code is only implemented for a couple of matrix formats.
5090 
5091 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5092 @*/
5093 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5094 {
5095   PetscFunctionBegin;
5096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5097   PetscValidType(mat, 1);
5098   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5099   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5100 
5101   if (!mat->cmap->N) {
5102     PetscCall(VecSet(v, 0.0));
5103     if (idx) {
5104       PetscInt i, m = mat->rmap->n;
5105       for (i = 0; i < m; i++) idx[i] = -1;
5106     }
5107   } else {
5108     MatCheckPreallocated(mat, 1);
5109     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5110     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5111   }
5112   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5113   PetscFunctionReturn(PETSC_SUCCESS);
5114 }
5115 
5116 /*@
5117    MatGetRowSum - Gets the sum of each row of the matrix
5118 
5119    Logically or Neighborhood Collective
5120 
5121    Input Parameter:
5122 .  mat - the matrix
5123 
5124    Output Parameter:
5125 .  v - the vector for storing the sum of rows
5126 
5127    Level: intermediate
5128 
5129    Notes:
5130     This code is slow since it is not currently specialized for different formats
5131 
5132 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5133 @*/
5134 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5135 {
5136   Vec ones;
5137 
5138   PetscFunctionBegin;
5139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5140   PetscValidType(mat, 1);
5141   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5143   MatCheckPreallocated(mat, 1);
5144   PetscCall(MatCreateVecs(mat, &ones, NULL));
5145   PetscCall(VecSet(ones, 1.));
5146   PetscCall(MatMult(mat, ones, v));
5147   PetscCall(VecDestroy(&ones));
5148   PetscFunctionReturn(PETSC_SUCCESS);
5149 }
5150 
5151 /*@
5152    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5153    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5154 
5155    Collective
5156 
5157    Input Parameter:
5158 .  mat - the matrix to provide the transpose
5159 
5160    Output Parameter:
5161 .  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
5162 
5163    Level: advanced
5164 
5165    Note:
5166    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
5167    routine allows bypassing that call.
5168 
5169 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5170 @*/
5171 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5172 {
5173   PetscContainer  rB = NULL;
5174   MatParentState *rb = NULL;
5175 
5176   PetscFunctionBegin;
5177   PetscCall(PetscNew(&rb));
5178   rb->id    = ((PetscObject)mat)->id;
5179   rb->state = 0;
5180   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5181   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5182   PetscCall(PetscContainerSetPointer(rB, rb));
5183   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5184   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5185   PetscCall(PetscObjectDereference((PetscObject)rB));
5186   PetscFunctionReturn(PETSC_SUCCESS);
5187 }
5188 
5189 /*@
5190    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5191 
5192    Collective
5193 
5194    Input Parameters:
5195 +  mat - the matrix to transpose
5196 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5197 
5198    Output Parameter:
5199 .  B - the transpose
5200 
5201    Level: intermediate
5202 
5203    Notes:
5204      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5205 
5206      `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
5207      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5208 
5209      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.
5210 
5211      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5212 
5213      If mat is unchanged from the last call this function returns immediately without recomputing the result
5214 
5215      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5216 
5217 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5218           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5219 @*/
5220 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5221 {
5222   PetscContainer  rB = NULL;
5223   MatParentState *rb = NULL;
5224 
5225   PetscFunctionBegin;
5226   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5227   PetscValidType(mat, 1);
5228   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5229   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5230   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5231   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5232   MatCheckPreallocated(mat, 1);
5233   if (reuse == MAT_REUSE_MATRIX) {
5234     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5235     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5236     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5237     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5238     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5239   }
5240 
5241   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5242   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5243     PetscUseTypeMethod(mat, transpose, reuse, B);
5244     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5245   }
5246   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5247 
5248   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5249   if (reuse != MAT_INPLACE_MATRIX) {
5250     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5251     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5252     rb->state        = ((PetscObject)mat)->state;
5253     rb->nonzerostate = mat->nonzerostate;
5254   }
5255   PetscFunctionReturn(PETSC_SUCCESS);
5256 }
5257 
5258 /*@
5259    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5260 
5261    Collective
5262 
5263    Input Parameter:
5264 .  A - the matrix to transpose
5265 
5266    Output Parameter:
5267 .  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
5268       numerical portion.
5269 
5270    Level: intermediate
5271 
5272    Note:
5273    This is not supported for many matrix types, use `MatTranspose()` in those cases
5274 
5275 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5276 @*/
5277 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5278 {
5279   PetscFunctionBegin;
5280   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5281   PetscValidType(A, 1);
5282   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5283   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5284   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5285   PetscUseTypeMethod(A, transposesymbolic, B);
5286   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5287 
5288   PetscCall(MatTransposeSetPrecursor(A, *B));
5289   PetscFunctionReturn(PETSC_SUCCESS);
5290 }
5291 
5292 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5293 {
5294   PetscContainer  rB;
5295   MatParentState *rb;
5296 
5297   PetscFunctionBegin;
5298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5299   PetscValidType(A, 1);
5300   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5301   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5302   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5303   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5304   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5305   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5306   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5307   PetscFunctionReturn(PETSC_SUCCESS);
5308 }
5309 
5310 /*@
5311    MatIsTranspose - Test whether a matrix is another one's transpose,
5312         or its own, in which case it tests symmetry.
5313 
5314    Collective
5315 
5316    Input Parameters:
5317 +  A - the matrix to test
5318 .  B - the matrix to test against, this can equal the first parameter
5319 -  tol - tolerance, differences between entries smaller than this are counted as zero
5320 
5321    Output Parameter:
5322 .  flg - the result
5323 
5324    Level: intermediate
5325 
5326    Notes:
5327    Only available for `MATAIJ` matrices.
5328 
5329    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5330    test involves parallel copies of the block-offdiagonal parts of the matrix.
5331 
5332 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5333 @*/
5334 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5335 {
5336   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5337 
5338   PetscFunctionBegin;
5339   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5340   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5341   PetscValidBoolPointer(flg, 4);
5342   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5343   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5344   *flg = PETSC_FALSE;
5345   if (f && g) {
5346     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5347     PetscCall((*f)(A, B, tol, flg));
5348   } else {
5349     MatType mattype;
5350 
5351     PetscCall(MatGetType(f ? B : A, &mattype));
5352     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5353   }
5354   PetscFunctionReturn(PETSC_SUCCESS);
5355 }
5356 
5357 /*@
5358    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5359 
5360    Collective
5361 
5362    Input Parameters:
5363 +  mat - the matrix to transpose and complex conjugate
5364 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5365 
5366    Output Parameter:
5367 .  B - the Hermitian transpose
5368 
5369    Level: intermediate
5370 
5371 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5372 @*/
5373 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5374 {
5375   PetscFunctionBegin;
5376   PetscCall(MatTranspose(mat, reuse, B));
5377 #if defined(PETSC_USE_COMPLEX)
5378   PetscCall(MatConjugate(*B));
5379 #endif
5380   PetscFunctionReturn(PETSC_SUCCESS);
5381 }
5382 
5383 /*@
5384    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5385 
5386    Collective
5387 
5388    Input Parameters:
5389 +  A - the matrix to test
5390 .  B - the matrix to test against, this can equal the first parameter
5391 -  tol - tolerance, differences between entries smaller than this are counted as zero
5392 
5393    Output Parameter:
5394 .  flg - the result
5395 
5396    Level: intermediate
5397 
5398    Notes:
5399    Only available for `MATAIJ` matrices.
5400 
5401    The sequential algorithm
5402    has a running time of the order of the number of nonzeros; the parallel
5403    test involves parallel copies of the block-offdiagonal parts of the matrix.
5404 
5405 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5406 @*/
5407 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5408 {
5409   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5410 
5411   PetscFunctionBegin;
5412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5413   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5414   PetscValidBoolPointer(flg, 4);
5415   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5416   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5417   if (f && g) {
5418     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5419     PetscCall((*f)(A, B, tol, flg));
5420   }
5421   PetscFunctionReturn(PETSC_SUCCESS);
5422 }
5423 
5424 /*@
5425    MatPermute - Creates a new matrix with rows and columns permuted from the
5426    original.
5427 
5428    Collective
5429 
5430    Input Parameters:
5431 +  mat - the matrix to permute
5432 .  row - row permutation, each processor supplies only the permutation for its rows
5433 -  col - column permutation, each processor supplies only the permutation for its columns
5434 
5435    Output Parameter:
5436 .  B - the permuted matrix
5437 
5438    Level: advanced
5439 
5440    Note:
5441    The index sets map from row/col of permuted matrix to row/col of original matrix.
5442    The index sets should be on the same communicator as mat and have the same local sizes.
5443 
5444    Developer Note:
5445      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5446      exploit the fact that row and col are permutations, consider implementing the
5447      more general `MatCreateSubMatrix()` instead.
5448 
5449 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5450 @*/
5451 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5452 {
5453   PetscFunctionBegin;
5454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5455   PetscValidType(mat, 1);
5456   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5457   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5458   PetscValidPointer(B, 4);
5459   PetscCheckSameComm(mat, 1, row, 2);
5460   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5463   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5464   MatCheckPreallocated(mat, 1);
5465 
5466   if (mat->ops->permute) {
5467     PetscUseTypeMethod(mat, permute, row, col, B);
5468     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5469   } else {
5470     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5471   }
5472   PetscFunctionReturn(PETSC_SUCCESS);
5473 }
5474 
5475 /*@
5476    MatEqual - Compares two matrices.
5477 
5478    Collective
5479 
5480    Input Parameters:
5481 +  A - the first matrix
5482 -  B - the second matrix
5483 
5484    Output Parameter:
5485 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5486 
5487    Level: intermediate
5488 
5489 .seealso: [](ch_matrices), `Mat`
5490 @*/
5491 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5492 {
5493   PetscFunctionBegin;
5494   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5495   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5496   PetscValidType(A, 1);
5497   PetscValidType(B, 2);
5498   PetscValidBoolPointer(flg, 3);
5499   PetscCheckSameComm(A, 1, B, 2);
5500   MatCheckPreallocated(A, 1);
5501   MatCheckPreallocated(B, 2);
5502   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5503   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5504   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,
5505              B->cmap->N);
5506   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5507     PetscUseTypeMethod(A, equal, B, flg);
5508   } else {
5509     PetscCall(MatMultEqual(A, B, 10, flg));
5510   }
5511   PetscFunctionReturn(PETSC_SUCCESS);
5512 }
5513 
5514 /*@
5515    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5516    matrices that are stored as vectors.  Either of the two scaling
5517    matrices can be `NULL`.
5518 
5519    Collective
5520 
5521    Input Parameters:
5522 +  mat - the matrix to be scaled
5523 .  l - the left scaling vector (or `NULL`)
5524 -  r - the right scaling vector (or `NULL`)
5525 
5526    Level: intermediate
5527 
5528    Note:
5529    `MatDiagonalScale()` computes A = LAR, where
5530    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5531    The L scales the rows of the matrix, the R scales the columns of the matrix.
5532 
5533 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5534 @*/
5535 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5536 {
5537   PetscFunctionBegin;
5538   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5539   PetscValidType(mat, 1);
5540   if (l) {
5541     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5542     PetscCheckSameComm(mat, 1, l, 2);
5543   }
5544   if (r) {
5545     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5546     PetscCheckSameComm(mat, 1, r, 3);
5547   }
5548   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5549   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5550   MatCheckPreallocated(mat, 1);
5551   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5552 
5553   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5554   PetscUseTypeMethod(mat, diagonalscale, l, r);
5555   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5556   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5557   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5558   PetscFunctionReturn(PETSC_SUCCESS);
5559 }
5560 
5561 /*@
5562     MatScale - Scales all elements of a matrix by a given number.
5563 
5564     Logically Collective
5565 
5566     Input Parameters:
5567 +   mat - the matrix to be scaled
5568 -   a  - the scaling value
5569 
5570     Level: intermediate
5571 
5572 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5573 @*/
5574 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5575 {
5576   PetscFunctionBegin;
5577   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5578   PetscValidType(mat, 1);
5579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5581   PetscValidLogicalCollectiveScalar(mat, a, 2);
5582   MatCheckPreallocated(mat, 1);
5583 
5584   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5585   if (a != (PetscScalar)1.0) {
5586     PetscUseTypeMethod(mat, scale, a);
5587     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5588   }
5589   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5590   PetscFunctionReturn(PETSC_SUCCESS);
5591 }
5592 
5593 /*@
5594    MatNorm - Calculates various norms of a matrix.
5595 
5596    Collective
5597 
5598    Input Parameters:
5599 +  mat - the matrix
5600 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5601 
5602    Output Parameter:
5603 .  nrm - the resulting norm
5604 
5605    Level: intermediate
5606 
5607 .seealso: [](ch_matrices), `Mat`
5608 @*/
5609 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5610 {
5611   PetscFunctionBegin;
5612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5613   PetscValidType(mat, 1);
5614   PetscValidRealPointer(nrm, 3);
5615 
5616   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5617   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5618   MatCheckPreallocated(mat, 1);
5619 
5620   PetscUseTypeMethod(mat, norm, type, nrm);
5621   PetscFunctionReturn(PETSC_SUCCESS);
5622 }
5623 
5624 /*
5625      This variable is used to prevent counting of MatAssemblyBegin() that
5626    are called from within a MatAssemblyEnd().
5627 */
5628 static PetscInt MatAssemblyEnd_InUse = 0;
5629 /*@
5630    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5631    be called after completing all calls to `MatSetValues()`.
5632 
5633    Collective
5634 
5635    Input Parameters:
5636 +  mat - the matrix
5637 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5638 
5639    Level: beginner
5640 
5641    Notes:
5642    `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5643    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5644 
5645    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5646    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5647    using the matrix.
5648 
5649    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5650    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
5651    a global collective operation requiring all processes that share the matrix.
5652 
5653    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5654    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5655    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5656 
5657 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5658 @*/
5659 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5660 {
5661   PetscFunctionBegin;
5662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5663   PetscValidType(mat, 1);
5664   MatCheckPreallocated(mat, 1);
5665   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5666   if (mat->assembled) {
5667     mat->was_assembled = PETSC_TRUE;
5668     mat->assembled     = PETSC_FALSE;
5669   }
5670 
5671   if (!MatAssemblyEnd_InUse) {
5672     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5673     PetscTryTypeMethod(mat, assemblybegin, type);
5674     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5675   } else PetscTryTypeMethod(mat, assemblybegin, type);
5676   PetscFunctionReturn(PETSC_SUCCESS);
5677 }
5678 
5679 /*@
5680    MatAssembled - Indicates if a matrix has been assembled and is ready for
5681      use; for example, in matrix-vector product.
5682 
5683    Not Collective
5684 
5685    Input Parameter:
5686 .  mat - the matrix
5687 
5688    Output Parameter:
5689 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5690 
5691    Level: advanced
5692 
5693 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5694 @*/
5695 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5696 {
5697   PetscFunctionBegin;
5698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5699   PetscValidBoolPointer(assembled, 2);
5700   *assembled = mat->assembled;
5701   PetscFunctionReturn(PETSC_SUCCESS);
5702 }
5703 
5704 /*@
5705    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5706    be called after `MatAssemblyBegin()`.
5707 
5708    Collective
5709 
5710    Input Parameters:
5711 +  mat - the matrix
5712 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5713 
5714    Options Database Keys:
5715 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5716 .  -mat_view ::ascii_info_detail - Prints more detailed info
5717 .  -mat_view - Prints matrix in ASCII format
5718 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5719 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5720 .  -display <name> - Sets display name (default is host)
5721 .  -draw_pause <sec> - Sets number of seconds to pause after display
5722 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5723 .  -viewer_socket_machine <machine> - Machine to use for socket
5724 .  -viewer_socket_port <port> - Port number to use for socket
5725 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5726 
5727    Level: beginner
5728 
5729 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5730 @*/
5731 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5732 {
5733   static PetscInt inassm = 0;
5734   PetscBool       flg    = PETSC_FALSE;
5735 
5736   PetscFunctionBegin;
5737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5738   PetscValidType(mat, 1);
5739 
5740   inassm++;
5741   MatAssemblyEnd_InUse++;
5742   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5743     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5744     PetscTryTypeMethod(mat, assemblyend, type);
5745     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5746   } else PetscTryTypeMethod(mat, assemblyend, type);
5747 
5748   /* Flush assembly is not a true assembly */
5749   if (type != MAT_FLUSH_ASSEMBLY) {
5750     if (mat->num_ass) {
5751       if (!mat->symmetry_eternal) {
5752         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5753         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5754       }
5755       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5756       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5757     }
5758     mat->num_ass++;
5759     mat->assembled        = PETSC_TRUE;
5760     mat->ass_nonzerostate = mat->nonzerostate;
5761   }
5762 
5763   mat->insertmode = NOT_SET_VALUES;
5764   MatAssemblyEnd_InUse--;
5765   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5766   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5767     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5768 
5769     if (mat->checksymmetryonassembly) {
5770       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5771       if (flg) {
5772         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5773       } else {
5774         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5775       }
5776     }
5777     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5778   }
5779   inassm--;
5780   PetscFunctionReturn(PETSC_SUCCESS);
5781 }
5782 
5783 /*@
5784    MatSetOption - Sets a parameter option for a matrix. Some options
5785    may be specific to certain storage formats.  Some options
5786    determine how values will be inserted (or added). Sorted,
5787    row-oriented input will generally assemble the fastest. The default
5788    is row-oriented.
5789 
5790    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5791 
5792    Input Parameters:
5793 +  mat - the matrix
5794 .  option - the option, one of those listed below (and possibly others),
5795 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5796 
5797   Options Describing Matrix Structure:
5798 +    `MAT_SPD` - symmetric positive definite
5799 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5800 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5801 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5802 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5803 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5804 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5805 
5806    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5807    do not need to be computed (usually at a high cost)
5808 
5809    Options For Use with `MatSetValues()`:
5810    Insert a logically dense subblock, which can be
5811 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5812 
5813    These options reflect the data you pass in with `MatSetValues()`; it has
5814    nothing to do with how the data is stored internally in the matrix
5815    data structure.
5816 
5817    When (re)assembling a matrix, we can restrict the input for
5818    efficiency/debugging purposes.  These options include
5819 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5820 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5821 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5822 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5823 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5824 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5825         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5826         performance for very large process counts.
5827 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5828         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5829         functions, instead sending only neighbor messages.
5830 
5831    Level: intermediate
5832 
5833    Notes:
5834    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5835 
5836    Some options are relevant only for particular matrix types and
5837    are thus ignored by others.  Other options are not supported by
5838    certain matrix types and will generate an error message if set.
5839 
5840    If using Fortran to compute a matrix, one may need to
5841    use the column-oriented option (or convert to the row-oriented
5842    format).
5843 
5844    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5845    that would generate a new entry in the nonzero structure is instead
5846    ignored.  Thus, if memory has not already been allocated for this particular
5847    data, then the insertion is ignored. For dense matrices, in which
5848    the entire array is allocated, no entries are ever ignored.
5849    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5850 
5851    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5852    that would generate a new entry in the nonzero structure instead produces
5853    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
5854 
5855    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5856    that would generate a new entry that has not been preallocated will
5857    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5858    only.) This is a useful flag when debugging matrix memory preallocation.
5859    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5860 
5861    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5862    other processors should be dropped, rather than stashed.
5863    This is useful if you know that the "owning" processor is also
5864    always generating the correct matrix entries, so that PETSc need
5865    not transfer duplicate entries generated on another processor.
5866 
5867    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5868    searches during matrix assembly. When this flag is set, the hash table
5869    is created during the first matrix assembly. This hash table is
5870    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5871    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5872    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5873    supported by `MATMPIBAIJ` format only.
5874 
5875    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5876    are kept in the nonzero structure
5877 
5878    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5879    a zero location in the matrix
5880 
5881    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5882 
5883    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5884         zero row routines and thus improves performance for very large process counts.
5885 
5886    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5887         part of the matrix (since they should match the upper triangular part).
5888 
5889    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5890                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5891                      with finite difference schemes with non-periodic boundary conditions.
5892 
5893    Developer Note:
5894    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5895    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5896    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5897    not changed.
5898 
5899 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5900 @*/
5901 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5902 {
5903   PetscFunctionBegin;
5904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5905   if (op > 0) {
5906     PetscValidLogicalCollectiveEnum(mat, op, 2);
5907     PetscValidLogicalCollectiveBool(mat, flg, 3);
5908   }
5909 
5910   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);
5911 
5912   switch (op) {
5913   case MAT_FORCE_DIAGONAL_ENTRIES:
5914     mat->force_diagonals = flg;
5915     PetscFunctionReturn(PETSC_SUCCESS);
5916   case MAT_NO_OFF_PROC_ENTRIES:
5917     mat->nooffprocentries = flg;
5918     PetscFunctionReturn(PETSC_SUCCESS);
5919   case MAT_SUBSET_OFF_PROC_ENTRIES:
5920     mat->assembly_subset = flg;
5921     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5922 #if !defined(PETSC_HAVE_MPIUNI)
5923       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5924 #endif
5925       mat->stash.first_assembly_done = PETSC_FALSE;
5926     }
5927     PetscFunctionReturn(PETSC_SUCCESS);
5928   case MAT_NO_OFF_PROC_ZERO_ROWS:
5929     mat->nooffproczerorows = flg;
5930     PetscFunctionReturn(PETSC_SUCCESS);
5931   case MAT_SPD:
5932     if (flg) {
5933       mat->spd                    = PETSC_BOOL3_TRUE;
5934       mat->symmetric              = PETSC_BOOL3_TRUE;
5935       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5936     } else {
5937       mat->spd = PETSC_BOOL3_FALSE;
5938     }
5939     break;
5940   case MAT_SYMMETRIC:
5941     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5942     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5943 #if !defined(PETSC_USE_COMPLEX)
5944     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5945 #endif
5946     break;
5947   case MAT_HERMITIAN:
5948     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5949     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5950 #if !defined(PETSC_USE_COMPLEX)
5951     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5952 #endif
5953     break;
5954   case MAT_STRUCTURALLY_SYMMETRIC:
5955     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5956     break;
5957   case MAT_SYMMETRY_ETERNAL:
5958     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");
5959     mat->symmetry_eternal = flg;
5960     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5961     break;
5962   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5963     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");
5964     mat->structural_symmetry_eternal = flg;
5965     break;
5966   case MAT_SPD_ETERNAL:
5967     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");
5968     mat->spd_eternal = flg;
5969     if (flg) {
5970       mat->structural_symmetry_eternal = PETSC_TRUE;
5971       mat->symmetry_eternal            = PETSC_TRUE;
5972     }
5973     break;
5974   case MAT_STRUCTURE_ONLY:
5975     mat->structure_only = flg;
5976     break;
5977   case MAT_SORTED_FULL:
5978     mat->sortedfull = flg;
5979     break;
5980   default:
5981     break;
5982   }
5983   PetscTryTypeMethod(mat, setoption, op, flg);
5984   PetscFunctionReturn(PETSC_SUCCESS);
5985 }
5986 
5987 /*@
5988    MatGetOption - Gets a parameter option that has been set for a matrix.
5989 
5990    Logically Collective
5991 
5992    Input Parameters:
5993 +  mat - the matrix
5994 -  option - the option, this only responds to certain options, check the code for which ones
5995 
5996    Output Parameter:
5997 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5998 
5999    Level: intermediate
6000 
6001     Notes:
6002     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6003 
6004     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6005     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6006 
6007 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6008     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6009 @*/
6010 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6011 {
6012   PetscFunctionBegin;
6013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6014   PetscValidType(mat, 1);
6015 
6016   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);
6017   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()");
6018 
6019   switch (op) {
6020   case MAT_NO_OFF_PROC_ENTRIES:
6021     *flg = mat->nooffprocentries;
6022     break;
6023   case MAT_NO_OFF_PROC_ZERO_ROWS:
6024     *flg = mat->nooffproczerorows;
6025     break;
6026   case MAT_SYMMETRIC:
6027     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6028     break;
6029   case MAT_HERMITIAN:
6030     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6031     break;
6032   case MAT_STRUCTURALLY_SYMMETRIC:
6033     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6034     break;
6035   case MAT_SPD:
6036     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6037     break;
6038   case MAT_SYMMETRY_ETERNAL:
6039     *flg = mat->symmetry_eternal;
6040     break;
6041   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6042     *flg = mat->symmetry_eternal;
6043     break;
6044   default:
6045     break;
6046   }
6047   PetscFunctionReturn(PETSC_SUCCESS);
6048 }
6049 
6050 /*@
6051    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6052    this routine retains the old nonzero structure.
6053 
6054    Logically Collective
6055 
6056    Input Parameter:
6057 .  mat - the matrix
6058 
6059    Level: intermediate
6060 
6061    Note:
6062     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.
6063    See the Performance chapter of the users manual for information on preallocating matrices.
6064 
6065 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6066 @*/
6067 PetscErrorCode MatZeroEntries(Mat mat)
6068 {
6069   PetscFunctionBegin;
6070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6071   PetscValidType(mat, 1);
6072   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6073   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");
6074   MatCheckPreallocated(mat, 1);
6075 
6076   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6077   PetscUseTypeMethod(mat, zeroentries);
6078   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6079   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6080   PetscFunctionReturn(PETSC_SUCCESS);
6081 }
6082 
6083 /*@
6084    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6085    of a set of rows and columns of a matrix.
6086 
6087    Collective
6088 
6089    Input Parameters:
6090 +  mat - the matrix
6091 .  numRows - the number of rows/columns to zero
6092 .  rows - the global row indices
6093 .  diag - value put in the diagonal of the eliminated rows
6094 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6095 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6096 
6097    Level: intermediate
6098 
6099    Notes:
6100    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6101 
6102    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6103    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
6104 
6105    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6106    Krylov method to take advantage of the known solution on the zeroed rows.
6107 
6108    For the parallel case, all processes that share the matrix (i.e.,
6109    those in the communicator used for matrix creation) MUST call this
6110    routine, regardless of whether any rows being zeroed are owned by
6111    them.
6112 
6113    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6114 
6115    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6116    list only rows local to itself).
6117 
6118    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6119 
6120 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6121           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6122 @*/
6123 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6124 {
6125   PetscFunctionBegin;
6126   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6127   PetscValidType(mat, 1);
6128   if (numRows) PetscValidIntPointer(rows, 3);
6129   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6130   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6131   MatCheckPreallocated(mat, 1);
6132 
6133   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6134   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6135   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6136   PetscFunctionReturn(PETSC_SUCCESS);
6137 }
6138 
6139 /*@
6140    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6141    of a set of rows and columns of a matrix.
6142 
6143    Collective
6144 
6145    Input Parameters:
6146 +  mat - the matrix
6147 .  is - the rows to zero
6148 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6149 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6150 -  b - optional vector of right hand side, that will be adjusted by provided solution
6151 
6152    Level: intermediate
6153 
6154    Note:
6155    See `MatZeroRowsColumns()` for details on how this routine operates.
6156 
6157 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6158           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6159 @*/
6160 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6161 {
6162   PetscInt        numRows;
6163   const PetscInt *rows;
6164 
6165   PetscFunctionBegin;
6166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6167   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6168   PetscValidType(mat, 1);
6169   PetscValidType(is, 2);
6170   PetscCall(ISGetLocalSize(is, &numRows));
6171   PetscCall(ISGetIndices(is, &rows));
6172   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6173   PetscCall(ISRestoreIndices(is, &rows));
6174   PetscFunctionReturn(PETSC_SUCCESS);
6175 }
6176 
6177 /*@
6178    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6179    of a set of rows of a matrix.
6180 
6181    Collective
6182 
6183    Input Parameters:
6184 +  mat - the matrix
6185 .  numRows - the number of rows to zero
6186 .  rows - the global row indices
6187 .  diag - value put in the diagonal of the zeroed rows
6188 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6189 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6190 
6191    Level: intermediate
6192 
6193    Notes:
6194    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6195 
6196    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6197 
6198    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6199    Krylov method to take advantage of the known solution on the zeroed rows.
6200 
6201    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)
6202    from the matrix.
6203 
6204    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6205    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
6206    formats this does not alter the nonzero structure.
6207 
6208    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6209    of the matrix is not changed the values are
6210    merely zeroed.
6211 
6212    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6213    formats can optionally remove the main diagonal entry from the
6214    nonzero structure as well, by passing 0.0 as the final argument).
6215 
6216    For the parallel case, all processes that share the matrix (i.e.,
6217    those in the communicator used for matrix creation) MUST call this
6218    routine, regardless of whether any rows being zeroed are owned by
6219    them.
6220 
6221    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6222    list only rows local to itself).
6223 
6224    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6225    owns that are to be zeroed. This saves a global synchronization in the implementation.
6226 
6227 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6228           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6229 @*/
6230 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6231 {
6232   PetscFunctionBegin;
6233   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6234   PetscValidType(mat, 1);
6235   if (numRows) PetscValidIntPointer(rows, 3);
6236   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6237   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6238   MatCheckPreallocated(mat, 1);
6239 
6240   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6241   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6242   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6243   PetscFunctionReturn(PETSC_SUCCESS);
6244 }
6245 
6246 /*@
6247    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6248    of a set of rows of a matrix.
6249 
6250    Collective
6251 
6252    Input Parameters:
6253 +  mat - the matrix
6254 .  is - index set of rows to remove (if `NULL` then no row is removed)
6255 .  diag - value put in all diagonals of eliminated rows
6256 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6257 -  b - optional vector of right hand side, that will be adjusted by provided solution
6258 
6259    Level: intermediate
6260 
6261    Note:
6262    See `MatZeroRows()` for details on how this routine operates.
6263 
6264 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6265           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6266 @*/
6267 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6268 {
6269   PetscInt        numRows = 0;
6270   const PetscInt *rows    = NULL;
6271 
6272   PetscFunctionBegin;
6273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6274   PetscValidType(mat, 1);
6275   if (is) {
6276     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6277     PetscCall(ISGetLocalSize(is, &numRows));
6278     PetscCall(ISGetIndices(is, &rows));
6279   }
6280   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6281   if (is) PetscCall(ISRestoreIndices(is, &rows));
6282   PetscFunctionReturn(PETSC_SUCCESS);
6283 }
6284 
6285 /*@
6286    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6287    of a set of rows of a matrix. These rows must be local to the process.
6288 
6289    Collective
6290 
6291    Input Parameters:
6292 +  mat - the matrix
6293 .  numRows - the number of rows to remove
6294 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6295 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6296 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6297 -  b - optional vector of right hand side, that will be adjusted by provided solution
6298 
6299    Level: intermediate
6300 
6301    Notes:
6302    See `MatZeroRows()` for details on how this routine operates.
6303 
6304    The grid coordinates are across the entire grid, not just the local portion
6305 
6306    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6307    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6308    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6309    `DM_BOUNDARY_PERIODIC` boundary type.
6310 
6311    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
6312    a single value per point) you can skip filling those indices.
6313 
6314    Fortran Note:
6315    `idxm` and `idxn` should be declared as
6316 $     MatStencil idxm(4, m)
6317    and the values inserted using
6318 .vb
6319     idxm(MatStencil_i, 1) = i
6320     idxm(MatStencil_j, 1) = j
6321     idxm(MatStencil_k, 1) = k
6322     idxm(MatStencil_c, 1) = c
6323    etc
6324 .ve
6325 
6326 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6327           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6328 @*/
6329 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6330 {
6331   PetscInt  dim    = mat->stencil.dim;
6332   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6333   PetscInt *dims   = mat->stencil.dims + 1;
6334   PetscInt *starts = mat->stencil.starts;
6335   PetscInt *dxm    = (PetscInt *)rows;
6336   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6337 
6338   PetscFunctionBegin;
6339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6340   PetscValidType(mat, 1);
6341   if (numRows) PetscValidPointer(rows, 3);
6342 
6343   PetscCall(PetscMalloc1(numRows, &jdxm));
6344   for (i = 0; i < numRows; ++i) {
6345     /* Skip unused dimensions (they are ordered k, j, i, c) */
6346     for (j = 0; j < 3 - sdim; ++j) dxm++;
6347     /* Local index in X dir */
6348     tmp = *dxm++ - starts[0];
6349     /* Loop over remaining dimensions */
6350     for (j = 0; j < dim - 1; ++j) {
6351       /* If nonlocal, set index to be negative */
6352       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6353       /* Update local index */
6354       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6355     }
6356     /* Skip component slot if necessary */
6357     if (mat->stencil.noc) dxm++;
6358     /* Local row number */
6359     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6360   }
6361   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6362   PetscCall(PetscFree(jdxm));
6363   PetscFunctionReturn(PETSC_SUCCESS);
6364 }
6365 
6366 /*@
6367    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6368    of a set of rows and columns of a matrix.
6369 
6370    Collective
6371 
6372    Input Parameters:
6373 +  mat - the matrix
6374 .  numRows - the number of rows/columns to remove
6375 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6376 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6377 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6378 -  b - optional vector of right hand side, that will be adjusted by provided solution
6379 
6380    Level: intermediate
6381 
6382    Notes:
6383    See `MatZeroRowsColumns()` for details on how this routine operates.
6384 
6385    The grid coordinates are across the entire grid, not just the local portion
6386 
6387    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6388    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6389    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6390    `DM_BOUNDARY_PERIODIC` boundary type.
6391 
6392    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
6393    a single value per point) you can skip filling those indices.
6394 
6395    Fortran Note:
6396    `idxm` and `idxn` should be declared as
6397 $     MatStencil idxm(4, m)
6398    and the values inserted using
6399 .vb
6400     idxm(MatStencil_i, 1) = i
6401     idxm(MatStencil_j, 1) = j
6402     idxm(MatStencil_k, 1) = k
6403     idxm(MatStencil_c, 1) = c
6404     etc
6405 .ve
6406 
6407 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6408           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6409 @*/
6410 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6411 {
6412   PetscInt  dim    = mat->stencil.dim;
6413   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6414   PetscInt *dims   = mat->stencil.dims + 1;
6415   PetscInt *starts = mat->stencil.starts;
6416   PetscInt *dxm    = (PetscInt *)rows;
6417   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6418 
6419   PetscFunctionBegin;
6420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6421   PetscValidType(mat, 1);
6422   if (numRows) PetscValidPointer(rows, 3);
6423 
6424   PetscCall(PetscMalloc1(numRows, &jdxm));
6425   for (i = 0; i < numRows; ++i) {
6426     /* Skip unused dimensions (they are ordered k, j, i, c) */
6427     for (j = 0; j < 3 - sdim; ++j) dxm++;
6428     /* Local index in X dir */
6429     tmp = *dxm++ - starts[0];
6430     /* Loop over remaining dimensions */
6431     for (j = 0; j < dim - 1; ++j) {
6432       /* If nonlocal, set index to be negative */
6433       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6434       /* Update local index */
6435       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6436     }
6437     /* Skip component slot if necessary */
6438     if (mat->stencil.noc) dxm++;
6439     /* Local row number */
6440     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6441   }
6442   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6443   PetscCall(PetscFree(jdxm));
6444   PetscFunctionReturn(PETSC_SUCCESS);
6445 }
6446 
6447 /*@C
6448    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6449    of a set of rows of a matrix; using local numbering of rows.
6450 
6451    Collective
6452 
6453    Input Parameters:
6454 +  mat - the matrix
6455 .  numRows - the number of rows to remove
6456 .  rows - the local row indices
6457 .  diag - value put in all diagonals of eliminated rows
6458 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6459 -  b - optional vector of right hand side, that will be adjusted by provided solution
6460 
6461    Level: intermediate
6462 
6463    Notes:
6464    Before calling `MatZeroRowsLocal()`, the user must first set the
6465    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6466 
6467    See `MatZeroRows()` for details on how this routine operates.
6468 
6469 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6470           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6471 @*/
6472 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6473 {
6474   PetscFunctionBegin;
6475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6476   PetscValidType(mat, 1);
6477   if (numRows) PetscValidIntPointer(rows, 3);
6478   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6479   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6480   MatCheckPreallocated(mat, 1);
6481 
6482   if (mat->ops->zerorowslocal) {
6483     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6484   } else {
6485     IS              is, newis;
6486     const PetscInt *newRows;
6487 
6488     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6489     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6490     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6491     PetscCall(ISGetIndices(newis, &newRows));
6492     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6493     PetscCall(ISRestoreIndices(newis, &newRows));
6494     PetscCall(ISDestroy(&newis));
6495     PetscCall(ISDestroy(&is));
6496   }
6497   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6498   PetscFunctionReturn(PETSC_SUCCESS);
6499 }
6500 
6501 /*@
6502    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6503    of a set of rows of a matrix; using local numbering of rows.
6504 
6505    Collective
6506 
6507    Input Parameters:
6508 +  mat - the matrix
6509 .  is - index set of rows to remove
6510 .  diag - value put in all diagonals of eliminated rows
6511 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6512 -  b - optional vector of right hand side, that will be adjusted by provided solution
6513 
6514    Level: intermediate
6515 
6516    Notes:
6517    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6518    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6519 
6520    See `MatZeroRows()` for details on how this routine operates.
6521 
6522 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6523           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6524 @*/
6525 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6526 {
6527   PetscInt        numRows;
6528   const PetscInt *rows;
6529 
6530   PetscFunctionBegin;
6531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6532   PetscValidType(mat, 1);
6533   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6534   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6535   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6536   MatCheckPreallocated(mat, 1);
6537 
6538   PetscCall(ISGetLocalSize(is, &numRows));
6539   PetscCall(ISGetIndices(is, &rows));
6540   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6541   PetscCall(ISRestoreIndices(is, &rows));
6542   PetscFunctionReturn(PETSC_SUCCESS);
6543 }
6544 
6545 /*@
6546    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6547    of a set of rows and columns of a matrix; using local numbering of rows.
6548 
6549    Collective
6550 
6551    Input Parameters:
6552 +  mat - the matrix
6553 .  numRows - the number of rows to remove
6554 .  rows - the global row indices
6555 .  diag - value put in all diagonals of eliminated rows
6556 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6557 -  b - optional vector of right hand side, that will be adjusted by provided solution
6558 
6559    Level: intermediate
6560 
6561    Notes:
6562    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6563    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6564 
6565    See `MatZeroRowsColumns()` for details on how this routine operates.
6566 
6567 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6568           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6569 @*/
6570 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6571 {
6572   IS              is, newis;
6573   const PetscInt *newRows;
6574 
6575   PetscFunctionBegin;
6576   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6577   PetscValidType(mat, 1);
6578   if (numRows) PetscValidIntPointer(rows, 3);
6579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6581   MatCheckPreallocated(mat, 1);
6582 
6583   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6584   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6585   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6586   PetscCall(ISGetIndices(newis, &newRows));
6587   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6588   PetscCall(ISRestoreIndices(newis, &newRows));
6589   PetscCall(ISDestroy(&newis));
6590   PetscCall(ISDestroy(&is));
6591   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6592   PetscFunctionReturn(PETSC_SUCCESS);
6593 }
6594 
6595 /*@
6596    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6597    of a set of rows and columns of a matrix; using local numbering of rows.
6598 
6599    Collective
6600 
6601    Input Parameters:
6602 +  mat - the matrix
6603 .  is - index set of rows to remove
6604 .  diag - value put in all diagonals of eliminated rows
6605 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6606 -  b - optional vector of right hand side, that will be adjusted by provided solution
6607 
6608    Level: intermediate
6609 
6610    Notes:
6611    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6612    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6613 
6614    See `MatZeroRowsColumns()` for details on how this routine operates.
6615 
6616 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6617           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6618 @*/
6619 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6620 {
6621   PetscInt        numRows;
6622   const PetscInt *rows;
6623 
6624   PetscFunctionBegin;
6625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6626   PetscValidType(mat, 1);
6627   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6628   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6629   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6630   MatCheckPreallocated(mat, 1);
6631 
6632   PetscCall(ISGetLocalSize(is, &numRows));
6633   PetscCall(ISGetIndices(is, &rows));
6634   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6635   PetscCall(ISRestoreIndices(is, &rows));
6636   PetscFunctionReturn(PETSC_SUCCESS);
6637 }
6638 
6639 /*@C
6640    MatGetSize - Returns the numbers of rows and columns in a matrix.
6641 
6642    Not Collective
6643 
6644    Input Parameter:
6645 .  mat - the matrix
6646 
6647    Output Parameters:
6648 +  m - the number of global rows
6649 -  n - the number of global columns
6650 
6651    Level: beginner
6652 
6653    Note:
6654    Both output parameters can be `NULL` on input.
6655 
6656 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6657 @*/
6658 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6659 {
6660   PetscFunctionBegin;
6661   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6662   if (m) *m = mat->rmap->N;
6663   if (n) *n = mat->cmap->N;
6664   PetscFunctionReturn(PETSC_SUCCESS);
6665 }
6666 
6667 /*@C
6668    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6669    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6670 
6671    Not Collective
6672 
6673    Input Parameter:
6674 .  mat - the matrix
6675 
6676    Output Parameters:
6677 +  m - the number of local rows, use `NULL` to not obtain this value
6678 -  n - the number of local columns, use `NULL` to not obtain this value
6679 
6680    Level: beginner
6681 
6682 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6683 @*/
6684 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6685 {
6686   PetscFunctionBegin;
6687   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6688   if (m) PetscValidIntPointer(m, 2);
6689   if (n) PetscValidIntPointer(n, 3);
6690   if (m) *m = mat->rmap->n;
6691   if (n) *n = mat->cmap->n;
6692   PetscFunctionReturn(PETSC_SUCCESS);
6693 }
6694 
6695 /*@C
6696    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6697    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6698 
6699    Not Collective, unless matrix has not been allocated, then collective
6700 
6701    Input Parameter:
6702 .  mat - the matrix
6703 
6704    Output Parameters:
6705 +  m - the global index of the first local column, use `NULL` to not obtain this value
6706 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6707 
6708    Level: developer
6709 
6710 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6711 @*/
6712 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6713 {
6714   PetscFunctionBegin;
6715   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6716   PetscValidType(mat, 1);
6717   if (m) PetscValidIntPointer(m, 2);
6718   if (n) PetscValidIntPointer(n, 3);
6719   MatCheckPreallocated(mat, 1);
6720   if (m) *m = mat->cmap->rstart;
6721   if (n) *n = mat->cmap->rend;
6722   PetscFunctionReturn(PETSC_SUCCESS);
6723 }
6724 
6725 /*@C
6726    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6727    this MPI process. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6728    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6729 
6730    Not Collective
6731 
6732    Input Parameter:
6733 .  mat - the matrix
6734 
6735    Output Parameters:
6736 +  m - the global index of the first local row, use `NULL` to not obtain this value
6737 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6738 
6739    Level: beginner
6740 
6741    Note:
6742   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6743   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6744   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6745 
6746 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6747           `PetscLayout`
6748 @*/
6749 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6750 {
6751   PetscFunctionBegin;
6752   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6753   PetscValidType(mat, 1);
6754   if (m) PetscValidIntPointer(m, 2);
6755   if (n) PetscValidIntPointer(n, 3);
6756   MatCheckPreallocated(mat, 1);
6757   if (m) *m = mat->rmap->rstart;
6758   if (n) *n = mat->rmap->rend;
6759   PetscFunctionReturn(PETSC_SUCCESS);
6760 }
6761 
6762 /*@C
6763    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6764    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
6765    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6766 
6767    Not Collective, unless matrix has not been allocated
6768 
6769    Input Parameter:
6770 .  mat - the matrix
6771 
6772    Output Parameter:
6773 .  ranges - start of each processors portion plus one more than the total length at the end
6774 
6775    Level: beginner
6776 
6777 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6778 @*/
6779 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6780 {
6781   PetscFunctionBegin;
6782   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6783   PetscValidType(mat, 1);
6784   MatCheckPreallocated(mat, 1);
6785   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6786   PetscFunctionReturn(PETSC_SUCCESS);
6787 }
6788 
6789 /*@C
6790    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6791    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6792 
6793    Not Collective, unless matrix has not been allocated
6794 
6795    Input Parameter:
6796 .  mat - the matrix
6797 
6798    Output Parameter:
6799 .  ranges - start of each processors portion plus one more then the total length at the end
6800 
6801    Level: beginner
6802 
6803 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6804 @*/
6805 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6806 {
6807   PetscFunctionBegin;
6808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6809   PetscValidType(mat, 1);
6810   MatCheckPreallocated(mat, 1);
6811   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6812   PetscFunctionReturn(PETSC_SUCCESS);
6813 }
6814 
6815 /*@C
6816    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6817    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6818    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6819 
6820    Not Collective
6821 
6822    Input Parameter:
6823 .  A - matrix
6824 
6825    Output Parameters:
6826 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6827 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6828 
6829    Level: intermediate
6830 
6831 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6832 @*/
6833 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6834 {
6835   PetscErrorCode (*f)(Mat, IS *, IS *);
6836 
6837   PetscFunctionBegin;
6838   MatCheckPreallocated(A, 1);
6839   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6840   if (f) {
6841     PetscCall((*f)(A, rows, cols));
6842   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6843     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6844     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6845   }
6846   PetscFunctionReturn(PETSC_SUCCESS);
6847 }
6848 
6849 /*@C
6850    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6851    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6852    to complete the factorization.
6853 
6854    Collective
6855 
6856    Input Parameters:
6857 +  fact - the factorized matrix obtained with `MatGetFactor()`
6858 .  mat - the matrix
6859 .  row - row permutation
6860 .  col - column permutation
6861 -  info - structure containing
6862 .vb
6863       levels - number of levels of fill.
6864       expected fill - as ratio of original fill.
6865       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6866                 missing diagonal entries)
6867 .ve
6868 
6869    Level: developer
6870 
6871    Notes:
6872    See [Matrix Factorization](sec_matfactor) for additional information.
6873 
6874    Most users should employ the `KSP` interface for linear solvers
6875    instead of working directly with matrix algebra routines such as this.
6876    See, e.g., `KSPCreate()`.
6877 
6878    Uses the definition of level of fill as in Y. Saad, 2003
6879 
6880    Developer Note:
6881    The Fortran interface is not autogenerated as the
6882    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6883 
6884    References:
6885 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6886 
6887 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6888           `MatGetOrdering()`, `MatFactorInfo`
6889 @*/
6890 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6891 {
6892   PetscFunctionBegin;
6893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6894   PetscValidType(mat, 2);
6895   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6896   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6897   PetscValidPointer(info, 5);
6898   PetscValidPointer(fact, 1);
6899   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6900   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6901   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6902   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6903   MatCheckPreallocated(mat, 2);
6904 
6905   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6906   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6907   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6908   PetscFunctionReturn(PETSC_SUCCESS);
6909 }
6910 
6911 /*@C
6912    MatICCFactorSymbolic - Performs symbolic incomplete
6913    Cholesky factorization for a symmetric matrix.  Use
6914    `MatCholeskyFactorNumeric()` to complete the factorization.
6915 
6916    Collective
6917 
6918    Input Parameters:
6919 +  fact - the factorized matrix obtained with `MatGetFactor()`
6920 .  mat - the matrix to be factored
6921 .  perm - row and column permutation
6922 -  info - structure containing
6923 .vb
6924       levels - number of levels of fill.
6925       expected fill - as ratio of original fill.
6926 .ve
6927 
6928    Level: developer
6929 
6930    Notes:
6931    Most users should employ the `KSP` interface for linear solvers
6932    instead of working directly with matrix algebra routines such as this.
6933    See, e.g., `KSPCreate()`.
6934 
6935    This uses the definition of level of fill as in Y. Saad, 2003
6936 
6937    Developer Note:
6938    The Fortran interface is not autogenerated as the
6939    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6940 
6941    References:
6942 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6943 
6944 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6945 @*/
6946 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6947 {
6948   PetscFunctionBegin;
6949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6950   PetscValidType(mat, 2);
6951   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6952   PetscValidPointer(info, 4);
6953   PetscValidPointer(fact, 1);
6954   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6955   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6956   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6957   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6958   MatCheckPreallocated(mat, 2);
6959 
6960   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6961   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6962   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6963   PetscFunctionReturn(PETSC_SUCCESS);
6964 }
6965 
6966 /*@C
6967    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6968    points to an array of valid matrices, they may be reused to store the new
6969    submatrices.
6970 
6971    Collective
6972 
6973    Input Parameters:
6974 +  mat - the matrix
6975 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6976 .  irow - index set of rows to extract
6977 .  icol - index set of columns to extract
6978 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6979 
6980    Output Parameter:
6981 .  submat - the array of submatrices
6982 
6983    Level: advanced
6984 
6985    Notes:
6986    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6987    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6988    to extract a parallel submatrix.
6989 
6990    Some matrix types place restrictions on the row and column
6991    indices, such as that they be sorted or that they be equal to each other.
6992 
6993    The index sets may not have duplicate entries.
6994 
6995    When extracting submatrices from a parallel matrix, each processor can
6996    form a different submatrix by setting the rows and columns of its
6997    individual index sets according to the local submatrix desired.
6998 
6999    When finished using the submatrices, the user should destroy
7000    them with `MatDestroySubMatrices()`.
7001 
7002    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7003    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7004 
7005    This routine creates the matrices in submat; you should NOT create them before
7006    calling it. It also allocates the array of matrix pointers submat.
7007 
7008    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7009    request one row/column in a block, they must request all rows/columns that are in
7010    that block. For example, if the block size is 2 you cannot request just row 0 and
7011    column 0.
7012 
7013    Fortran Note:
7014    The Fortran interface is slightly different from that given below; it
7015    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7016 
7017 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7018 @*/
7019 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7020 {
7021   PetscInt  i;
7022   PetscBool eq;
7023 
7024   PetscFunctionBegin;
7025   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7026   PetscValidType(mat, 1);
7027   if (n) {
7028     PetscValidPointer(irow, 3);
7029     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7030     PetscValidPointer(icol, 4);
7031     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7032   }
7033   PetscValidPointer(submat, 6);
7034   if (n && scall == MAT_REUSE_MATRIX) {
7035     PetscValidPointer(*submat, 6);
7036     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7037   }
7038   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7039   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7040   MatCheckPreallocated(mat, 1);
7041   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7042   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7043   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7044   for (i = 0; i < n; i++) {
7045     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7046     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7047     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7048 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7049     if (mat->boundtocpu && mat->bindingpropagates) {
7050       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7051       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7052     }
7053 #endif
7054   }
7055   PetscFunctionReturn(PETSC_SUCCESS);
7056 }
7057 
7058 /*@C
7059    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7060 
7061    Collective
7062 
7063    Input Parameters:
7064 +  mat - the matrix
7065 .  n   - the number of submatrixes to be extracted
7066 .  irow - index set of rows to extract
7067 .  icol - index set of columns to extract
7068 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7069 
7070    Output Parameter:
7071 .  submat - the array of submatrices
7072 
7073    Level: advanced
7074 
7075    Note:
7076    This is used by `PCGASM`
7077 
7078 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7079 @*/
7080 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7081 {
7082   PetscInt  i;
7083   PetscBool eq;
7084 
7085   PetscFunctionBegin;
7086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7087   PetscValidType(mat, 1);
7088   if (n) {
7089     PetscValidPointer(irow, 3);
7090     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7091     PetscValidPointer(icol, 4);
7092     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7093   }
7094   PetscValidPointer(submat, 6);
7095   if (n && scall == MAT_REUSE_MATRIX) {
7096     PetscValidPointer(*submat, 6);
7097     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7098   }
7099   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7100   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7101   MatCheckPreallocated(mat, 1);
7102 
7103   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7104   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7105   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7106   for (i = 0; i < n; i++) {
7107     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7108     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7109   }
7110   PetscFunctionReturn(PETSC_SUCCESS);
7111 }
7112 
7113 /*@C
7114    MatDestroyMatrices - Destroys an array of matrices.
7115 
7116    Collective
7117 
7118    Input Parameters:
7119 +  n - the number of local matrices
7120 -  mat - the matrices (this is a pointer to the array of matrices)
7121 
7122    Level: advanced
7123 
7124     Note:
7125     Frees not only the matrices, but also the array that contains the matrices
7126 
7127     Fortran Note:
7128     This does not free the array.
7129 
7130 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7131 @*/
7132 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7133 {
7134   PetscInt i;
7135 
7136   PetscFunctionBegin;
7137   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7138   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7139   PetscValidPointer(mat, 2);
7140 
7141   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7142 
7143   /* memory is allocated even if n = 0 */
7144   PetscCall(PetscFree(*mat));
7145   PetscFunctionReturn(PETSC_SUCCESS);
7146 }
7147 
7148 /*@C
7149    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7150 
7151    Collective
7152 
7153    Input Parameters:
7154 +  n - the number of local matrices
7155 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7156                        sequence of `MatCreateSubMatrices()`)
7157 
7158    Level: advanced
7159 
7160     Note:
7161     Frees not only the matrices, but also the array that contains the matrices
7162 
7163     Fortran Note:
7164     This does not free the array.
7165 
7166 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7167 @*/
7168 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7169 {
7170   Mat mat0;
7171 
7172   PetscFunctionBegin;
7173   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7174   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7175   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7176   PetscValidPointer(mat, 2);
7177 
7178   mat0 = (*mat)[0];
7179   if (mat0 && mat0->ops->destroysubmatrices) {
7180     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7181   } else {
7182     PetscCall(MatDestroyMatrices(n, mat));
7183   }
7184   PetscFunctionReturn(PETSC_SUCCESS);
7185 }
7186 
7187 /*@C
7188    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7189 
7190    Collective
7191 
7192    Input Parameter:
7193 .  mat - the matrix
7194 
7195    Output Parameter:
7196 .  matstruct - the sequential matrix with the nonzero structure of mat
7197 
7198   Level: developer
7199 
7200 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7201 @*/
7202 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7203 {
7204   PetscFunctionBegin;
7205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7206   PetscValidPointer(matstruct, 2);
7207 
7208   PetscValidType(mat, 1);
7209   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7210   MatCheckPreallocated(mat, 1);
7211 
7212   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7213   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7214   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7215   PetscFunctionReturn(PETSC_SUCCESS);
7216 }
7217 
7218 /*@C
7219    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7220 
7221    Collective
7222 
7223    Input Parameter:
7224 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7225                        sequence of `MatGetSeqNonzeroStructure()`)
7226 
7227    Level: advanced
7228 
7229     Note:
7230     Frees not only the matrices, but also the array that contains the matrices
7231 
7232 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7233 @*/
7234 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7235 {
7236   PetscFunctionBegin;
7237   PetscValidPointer(mat, 1);
7238   PetscCall(MatDestroy(mat));
7239   PetscFunctionReturn(PETSC_SUCCESS);
7240 }
7241 
7242 /*@
7243    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7244    replaces the index sets by larger ones that represent submatrices with
7245    additional overlap.
7246 
7247    Collective
7248 
7249    Input Parameters:
7250 +  mat - the matrix
7251 .  n   - the number of index sets
7252 .  is  - the array of index sets (these index sets will changed during the call)
7253 -  ov  - the additional overlap requested
7254 
7255    Options Database Key:
7256 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7257 
7258    Level: developer
7259 
7260    Note:
7261    The computed overlap preserves the matrix block sizes when the blocks are square.
7262    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7263    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7264 
7265 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7266 @*/
7267 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7268 {
7269   PetscInt i, bs, cbs;
7270 
7271   PetscFunctionBegin;
7272   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7273   PetscValidType(mat, 1);
7274   PetscValidLogicalCollectiveInt(mat, n, 2);
7275   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7276   if (n) {
7277     PetscValidPointer(is, 3);
7278     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7279   }
7280   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7281   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7282   MatCheckPreallocated(mat, 1);
7283 
7284   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7285   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7286   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7287   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7288   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7289   if (bs == cbs) {
7290     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7291   }
7292   PetscFunctionReturn(PETSC_SUCCESS);
7293 }
7294 
7295 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7296 
7297 /*@
7298    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7299    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7300    additional overlap.
7301 
7302    Collective
7303 
7304    Input Parameters:
7305 +  mat - the matrix
7306 .  n   - the number of index sets
7307 .  is  - the array of index sets (these index sets will changed during the call)
7308 -  ov  - the additional overlap requested
7309 
7310 `   Options Database Key:
7311 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7312 
7313    Level: developer
7314 
7315 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7316 @*/
7317 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7318 {
7319   PetscInt i;
7320 
7321   PetscFunctionBegin;
7322   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7323   PetscValidType(mat, 1);
7324   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7325   if (n) {
7326     PetscValidPointer(is, 3);
7327     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7328   }
7329   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7330   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7331   MatCheckPreallocated(mat, 1);
7332   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7333   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7334   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7335   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7336   PetscFunctionReturn(PETSC_SUCCESS);
7337 }
7338 
7339 /*@
7340    MatGetBlockSize - Returns the matrix block size.
7341 
7342    Not Collective
7343 
7344    Input Parameter:
7345 .  mat - the matrix
7346 
7347    Output Parameter:
7348 .  bs - block size
7349 
7350    Level: intermediate
7351 
7352    Notes:
7353     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7354 
7355    If the block size has not been set yet this routine returns 1.
7356 
7357 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7358 @*/
7359 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7360 {
7361   PetscFunctionBegin;
7362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7363   PetscValidIntPointer(bs, 2);
7364   *bs = PetscAbs(mat->rmap->bs);
7365   PetscFunctionReturn(PETSC_SUCCESS);
7366 }
7367 
7368 /*@
7369    MatGetBlockSizes - Returns the matrix block row and column sizes.
7370 
7371    Not Collective
7372 
7373    Input Parameter:
7374 .  mat - the matrix
7375 
7376    Output Parameters:
7377 +  rbs - row block size
7378 -  cbs - column block size
7379 
7380    Level: intermediate
7381 
7382    Notes:
7383     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7384     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7385 
7386    If a block size has not been set yet this routine returns 1.
7387 
7388 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7389 @*/
7390 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7391 {
7392   PetscFunctionBegin;
7393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7394   if (rbs) PetscValidIntPointer(rbs, 2);
7395   if (cbs) PetscValidIntPointer(cbs, 3);
7396   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7397   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7398   PetscFunctionReturn(PETSC_SUCCESS);
7399 }
7400 
7401 /*@
7402    MatSetBlockSize - Sets the matrix block size.
7403 
7404    Logically Collective
7405 
7406    Input Parameters:
7407 +  mat - the matrix
7408 -  bs - block size
7409 
7410    Level: intermediate
7411 
7412    Notes:
7413     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7414     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7415 
7416     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7417     is compatible with the matrix local sizes.
7418 
7419 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7420 @*/
7421 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7422 {
7423   PetscFunctionBegin;
7424   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7425   PetscValidLogicalCollectiveInt(mat, bs, 2);
7426   PetscCall(MatSetBlockSizes(mat, bs, bs));
7427   PetscFunctionReturn(PETSC_SUCCESS);
7428 }
7429 
7430 typedef struct {
7431   PetscInt         n;
7432   IS              *is;
7433   Mat             *mat;
7434   PetscObjectState nonzerostate;
7435   Mat              C;
7436 } EnvelopeData;
7437 
7438 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7439 {
7440   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7441   PetscCall(PetscFree(edata->is));
7442   PetscCall(PetscFree(edata));
7443   return PETSC_SUCCESS;
7444 }
7445 
7446 /*
7447    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7448          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7449 
7450    Collective
7451 
7452    Input Parameter:
7453 .  mat - the matrix
7454 
7455    Notes:
7456      There can be zeros within the blocks
7457 
7458      The blocks can overlap between processes, including laying on more than two processes
7459 
7460 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7461 */
7462 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7463 {
7464   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7465   PetscInt          *diag, *odiag, sc;
7466   VecScatter         scatter;
7467   PetscScalar       *seqv;
7468   const PetscScalar *parv;
7469   const PetscInt    *ia, *ja;
7470   PetscBool          set, flag, done;
7471   Mat                AA = mat, A;
7472   MPI_Comm           comm;
7473   PetscMPIInt        rank, size, tag;
7474   MPI_Status         status;
7475   PetscContainer     container;
7476   EnvelopeData      *edata;
7477   Vec                seq, par;
7478   IS                 isglobal;
7479 
7480   PetscFunctionBegin;
7481   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7482   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7483   if (!set || !flag) {
7484     /* TOO: only needs nonzero structure of transpose */
7485     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7486     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7487   }
7488   PetscCall(MatAIJGetLocalMat(AA, &A));
7489   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7490   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7491 
7492   PetscCall(MatGetLocalSize(mat, &n, NULL));
7493   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7494   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7495   PetscCallMPI(MPI_Comm_size(comm, &size));
7496   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7497 
7498   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7499 
7500   if (rank > 0) {
7501     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7502     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7503   }
7504   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7505   for (i = 0; i < n; i++) {
7506     env = PetscMax(env, ja[ia[i + 1] - 1]);
7507     II  = rstart + i;
7508     if (env == II) {
7509       starts[lblocks]  = tbs;
7510       sizes[lblocks++] = 1 + II - tbs;
7511       tbs              = 1 + II;
7512     }
7513   }
7514   if (rank < size - 1) {
7515     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7516     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7517   }
7518 
7519   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7520   if (!set || !flag) PetscCall(MatDestroy(&AA));
7521   PetscCall(MatDestroy(&A));
7522 
7523   PetscCall(PetscNew(&edata));
7524   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7525   edata->n = lblocks;
7526   /* create IS needed for extracting blocks from the original matrix */
7527   PetscCall(PetscMalloc1(lblocks, &edata->is));
7528   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7529 
7530   /* Create the resulting inverse matrix structure with preallocation information */
7531   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7532   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7533   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7534   PetscCall(MatSetType(edata->C, MATAIJ));
7535 
7536   /* Communicate the start and end of each row, from each block to the correct rank */
7537   /* TODO: Use PetscSF instead of VecScatter */
7538   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7539   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7540   PetscCall(VecGetArrayWrite(seq, &seqv));
7541   for (PetscInt i = 0; i < lblocks; i++) {
7542     for (PetscInt j = 0; j < sizes[i]; j++) {
7543       seqv[cnt]     = starts[i];
7544       seqv[cnt + 1] = starts[i] + sizes[i];
7545       cnt += 2;
7546     }
7547   }
7548   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7549   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7550   sc -= cnt;
7551   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7552   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7553   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7554   PetscCall(ISDestroy(&isglobal));
7555   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7556   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7557   PetscCall(VecScatterDestroy(&scatter));
7558   PetscCall(VecDestroy(&seq));
7559   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7560   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7561   PetscCall(VecGetArrayRead(par, &parv));
7562   cnt = 0;
7563   PetscCall(MatGetSize(mat, NULL, &n));
7564   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7565     PetscInt start, end, d = 0, od = 0;
7566 
7567     start = (PetscInt)PetscRealPart(parv[cnt]);
7568     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7569     cnt += 2;
7570 
7571     if (start < cstart) {
7572       od += cstart - start + n - cend;
7573       d += cend - cstart;
7574     } else if (start < cend) {
7575       od += n - cend;
7576       d += cend - start;
7577     } else od += n - start;
7578     if (end <= cstart) {
7579       od -= cstart - end + n - cend;
7580       d -= cend - cstart;
7581     } else if (end < cend) {
7582       od -= n - cend;
7583       d -= cend - end;
7584     } else od -= n - end;
7585 
7586     odiag[i] = od;
7587     diag[i]  = d;
7588   }
7589   PetscCall(VecRestoreArrayRead(par, &parv));
7590   PetscCall(VecDestroy(&par));
7591   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7592   PetscCall(PetscFree2(diag, odiag));
7593   PetscCall(PetscFree2(sizes, starts));
7594 
7595   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7596   PetscCall(PetscContainerSetPointer(container, edata));
7597   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7598   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7599   PetscCall(PetscObjectDereference((PetscObject)container));
7600   PetscFunctionReturn(PETSC_SUCCESS);
7601 }
7602 
7603 /*@
7604   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7605 
7606   Collective
7607 
7608   Input Parameters:
7609 + A - the matrix
7610 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7611 
7612   Output Parameter:
7613 . C - matrix with inverted block diagonal of `A`
7614 
7615   Level: advanced
7616 
7617   Note:
7618      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7619 
7620 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7621 @*/
7622 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7623 {
7624   PetscContainer   container;
7625   EnvelopeData    *edata;
7626   PetscObjectState nonzerostate;
7627 
7628   PetscFunctionBegin;
7629   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7630   if (!container) {
7631     PetscCall(MatComputeVariableBlockEnvelope(A));
7632     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7633   }
7634   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7635   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7636   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7637   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7638 
7639   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7640   *C = edata->C;
7641 
7642   for (PetscInt i = 0; i < edata->n; i++) {
7643     Mat          D;
7644     PetscScalar *dvalues;
7645 
7646     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7647     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7648     PetscCall(MatSeqDenseInvert(D));
7649     PetscCall(MatDenseGetArray(D, &dvalues));
7650     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7651     PetscCall(MatDestroy(&D));
7652   }
7653   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7654   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7655   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7656   PetscFunctionReturn(PETSC_SUCCESS);
7657 }
7658 
7659 /*@
7660    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7661 
7662    Logically Collective
7663 
7664    Input Parameters:
7665 +  mat - the matrix
7666 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7667 -  bsizes - the block sizes
7668 
7669    Level: intermediate
7670 
7671    Notes:
7672     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7673 
7674     Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7675 
7676 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7677           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7678 @*/
7679 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7680 {
7681   PetscInt i, ncnt = 0, nlocal;
7682 
7683   PetscFunctionBegin;
7684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7685   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7686   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7687   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7688   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);
7689   PetscCall(PetscFree(mat->bsizes));
7690   mat->nblocks = nblocks;
7691   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7692   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7693   PetscFunctionReturn(PETSC_SUCCESS);
7694 }
7695 
7696 /*@C
7697    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7698 
7699    Logically Collective; No Fortran Support
7700 
7701    Input Parameter:
7702 .  mat - the matrix
7703 
7704    Output Parameters:
7705 +  nblocks - the number of blocks on this process
7706 -  bsizes - the block sizes
7707 
7708    Level: intermediate
7709 
7710 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7711 @*/
7712 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7713 {
7714   PetscFunctionBegin;
7715   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7716   *nblocks = mat->nblocks;
7717   *bsizes  = mat->bsizes;
7718   PetscFunctionReturn(PETSC_SUCCESS);
7719 }
7720 
7721 /*@
7722    MatSetBlockSizes - Sets the matrix block row and column sizes.
7723 
7724    Logically Collective
7725 
7726    Input Parameters:
7727 +  mat - the matrix
7728 .  rbs - row block size
7729 -  cbs - column block size
7730 
7731    Level: intermediate
7732 
7733    Notes:
7734     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7735     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7736     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7737 
7738     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7739     are compatible with the matrix local sizes.
7740 
7741     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7742 
7743 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7744 @*/
7745 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7746 {
7747   PetscFunctionBegin;
7748   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7749   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7750   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7751   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7752   if (mat->rmap->refcnt) {
7753     ISLocalToGlobalMapping l2g  = NULL;
7754     PetscLayout            nmap = NULL;
7755 
7756     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7757     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7758     PetscCall(PetscLayoutDestroy(&mat->rmap));
7759     mat->rmap          = nmap;
7760     mat->rmap->mapping = l2g;
7761   }
7762   if (mat->cmap->refcnt) {
7763     ISLocalToGlobalMapping l2g  = NULL;
7764     PetscLayout            nmap = NULL;
7765 
7766     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7767     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7768     PetscCall(PetscLayoutDestroy(&mat->cmap));
7769     mat->cmap          = nmap;
7770     mat->cmap->mapping = l2g;
7771   }
7772   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7773   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7774   PetscFunctionReturn(PETSC_SUCCESS);
7775 }
7776 
7777 /*@
7778    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7779 
7780    Logically Collective
7781 
7782    Input Parameters:
7783 +  mat - the matrix
7784 .  fromRow - matrix from which to copy row block size
7785 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7786 
7787    Level: developer
7788 
7789 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7790 @*/
7791 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7792 {
7793   PetscFunctionBegin;
7794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7795   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7796   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7797   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7798   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7799   PetscFunctionReturn(PETSC_SUCCESS);
7800 }
7801 
7802 /*@
7803    MatResidual - Default routine to calculate the residual r = b - Ax
7804 
7805    Collective
7806 
7807    Input Parameters:
7808 +  mat - the matrix
7809 .  b   - the right-hand-side
7810 -  x   - the approximate solution
7811 
7812    Output Parameter:
7813 .  r - location to store the residual
7814 
7815    Level: developer
7816 
7817 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7818 @*/
7819 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7820 {
7821   PetscFunctionBegin;
7822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7823   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7824   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7825   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7826   PetscValidType(mat, 1);
7827   MatCheckPreallocated(mat, 1);
7828   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7829   if (!mat->ops->residual) {
7830     PetscCall(MatMult(mat, x, r));
7831     PetscCall(VecAYPX(r, -1.0, b));
7832   } else {
7833     PetscUseTypeMethod(mat, residual, b, x, r);
7834   }
7835   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7836   PetscFunctionReturn(PETSC_SUCCESS);
7837 }
7838 
7839 /*MC
7840     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7841 
7842     Synopsis:
7843     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7844 
7845     Not Collective
7846 
7847     Input Parameters:
7848 +   A - the matrix
7849 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7850 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7851 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7852                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7853                  always used.
7854 
7855     Output Parameters:
7856 +   n - number of local rows in the (possibly compressed) matrix
7857 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7858 .   ja - the column indices
7859 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7860            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7861 
7862     Level: developer
7863 
7864     Note:
7865     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7866 
7867 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7868 M*/
7869 
7870 /*MC
7871     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7872 
7873     Synopsis:
7874     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7875 
7876     Not Collective
7877 
7878     Input Parameters:
7879 +   A - the  matrix
7880 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7881 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7882     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7883                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7884                  always used.
7885 .   n - number of local rows in the (possibly compressed) matrix
7886 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7887 .   ja - the column indices
7888 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7889            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7890 
7891     Level: developer
7892 
7893 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7894 M*/
7895 
7896 /*@C
7897     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7898 
7899    Collective
7900 
7901     Input Parameters:
7902 +   mat - the matrix
7903 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7904 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7905 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7906                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7907                  always used.
7908 
7909     Output Parameters:
7910 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7911 .   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
7912 .   ja - the column indices, use `NULL` if not needed
7913 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7914            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7915 
7916     Level: developer
7917 
7918     Notes:
7919     You CANNOT change any of the ia[] or ja[] values.
7920 
7921     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7922 
7923     Fortran Notes:
7924     Use
7925 .vb
7926     PetscInt, pointer :: ia(:),ja(:)
7927     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7928     ! Access the ith and jth entries via ia(i) and ja(j)
7929 .ve
7930    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7931 
7932 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7933 @*/
7934 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7935 {
7936   PetscFunctionBegin;
7937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7938   PetscValidType(mat, 1);
7939   if (n) PetscValidIntPointer(n, 5);
7940   if (ia) PetscValidPointer(ia, 6);
7941   if (ja) PetscValidPointer(ja, 7);
7942   if (done) PetscValidBoolPointer(done, 8);
7943   MatCheckPreallocated(mat, 1);
7944   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7945   else {
7946     if (done) *done = PETSC_TRUE;
7947     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7948     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7949     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7950   }
7951   PetscFunctionReturn(PETSC_SUCCESS);
7952 }
7953 
7954 /*@C
7955     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7956 
7957     Collective
7958 
7959     Input Parameters:
7960 +   mat - the matrix
7961 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7962 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7963                 symmetrized
7964 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7965                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7966                  always used.
7967 .   n - number of columns in the (possibly compressed) matrix
7968 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7969 -   ja - the row indices
7970 
7971     Output Parameter:
7972 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7973 
7974     Level: developer
7975 
7976 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7977 @*/
7978 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7979 {
7980   PetscFunctionBegin;
7981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7982   PetscValidType(mat, 1);
7983   PetscValidIntPointer(n, 5);
7984   if (ia) PetscValidPointer(ia, 6);
7985   if (ja) PetscValidPointer(ja, 7);
7986   PetscValidBoolPointer(done, 8);
7987   MatCheckPreallocated(mat, 1);
7988   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7989   else {
7990     *done = PETSC_TRUE;
7991     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7992   }
7993   PetscFunctionReturn(PETSC_SUCCESS);
7994 }
7995 
7996 /*@C
7997     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7998 
7999     Collective
8000 
8001     Input Parameters:
8002 +   mat - the matrix
8003 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8004 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8005 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8006                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8007                  always used.
8008 .   n - size of (possibly compressed) matrix
8009 .   ia - the row pointers
8010 -   ja - the column indices
8011 
8012     Output Parameter:
8013 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8014 
8015     Level: developer
8016 
8017     Note:
8018     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8019     us of the array after it has been restored. If you pass `NULL`, it will
8020     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8021 
8022     Fortran Note:
8023    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8024 
8025 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8026 @*/
8027 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8028 {
8029   PetscFunctionBegin;
8030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8031   PetscValidType(mat, 1);
8032   if (ia) PetscValidPointer(ia, 6);
8033   if (ja) PetscValidPointer(ja, 7);
8034   if (done) PetscValidBoolPointer(done, 8);
8035   MatCheckPreallocated(mat, 1);
8036 
8037   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8038   else {
8039     if (done) *done = PETSC_TRUE;
8040     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8041     if (n) *n = 0;
8042     if (ia) *ia = NULL;
8043     if (ja) *ja = NULL;
8044   }
8045   PetscFunctionReturn(PETSC_SUCCESS);
8046 }
8047 
8048 /*@C
8049     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8050 
8051     Collective
8052 
8053     Input Parameters:
8054 +   mat - the matrix
8055 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8056 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8057 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8058                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8059                  always used.
8060 
8061     Output Parameters:
8062 +   n - size of (possibly compressed) matrix
8063 .   ia - the column pointers
8064 .   ja - the row indices
8065 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8066 
8067     Level: developer
8068 
8069 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8070 @*/
8071 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8072 {
8073   PetscFunctionBegin;
8074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8075   PetscValidType(mat, 1);
8076   if (ia) PetscValidPointer(ia, 6);
8077   if (ja) PetscValidPointer(ja, 7);
8078   PetscValidBoolPointer(done, 8);
8079   MatCheckPreallocated(mat, 1);
8080 
8081   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8082   else {
8083     *done = PETSC_TRUE;
8084     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8085     if (n) *n = 0;
8086     if (ia) *ia = NULL;
8087     if (ja) *ja = NULL;
8088   }
8089   PetscFunctionReturn(PETSC_SUCCESS);
8090 }
8091 
8092 /*@C
8093     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8094 
8095     Collective
8096 
8097     Input Parameters:
8098 +   mat - the matrix
8099 .   ncolors - maximum color value
8100 .   n   - number of entries in colorarray
8101 -   colorarray - array indicating color for each column
8102 
8103     Output Parameter:
8104 .   iscoloring - coloring generated using colorarray information
8105 
8106     Level: developer
8107 
8108 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8109 @*/
8110 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8111 {
8112   PetscFunctionBegin;
8113   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8114   PetscValidType(mat, 1);
8115   PetscValidIntPointer(colorarray, 4);
8116   PetscValidPointer(iscoloring, 5);
8117   MatCheckPreallocated(mat, 1);
8118 
8119   if (!mat->ops->coloringpatch) {
8120     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8121   } else {
8122     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8123   }
8124   PetscFunctionReturn(PETSC_SUCCESS);
8125 }
8126 
8127 /*@
8128    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8129 
8130    Logically Collective
8131 
8132    Input Parameter:
8133 .  mat - the factored matrix to be reset
8134 
8135    Level: developer
8136 
8137    Notes:
8138    This routine should be used only with factored matrices formed by in-place
8139    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8140    format).  This option can save memory, for example, when solving nonlinear
8141    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8142    ILU(0) preconditioner.
8143 
8144    One can specify in-place ILU(0) factorization by calling
8145 .vb
8146      PCType(pc,PCILU);
8147      PCFactorSeUseInPlace(pc);
8148 .ve
8149    or by using the options -pc_type ilu -pc_factor_in_place
8150 
8151    In-place factorization ILU(0) can also be used as a local
8152    solver for the blocks within the block Jacobi or additive Schwarz
8153    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8154    for details on setting local solver options.
8155 
8156    Most users should employ the `KSP` interface for linear solvers
8157    instead of working directly with matrix algebra routines such as this.
8158    See, e.g., `KSPCreate()`.
8159 
8160 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8161 @*/
8162 PetscErrorCode MatSetUnfactored(Mat mat)
8163 {
8164   PetscFunctionBegin;
8165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8166   PetscValidType(mat, 1);
8167   MatCheckPreallocated(mat, 1);
8168   mat->factortype = MAT_FACTOR_NONE;
8169   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8170   PetscUseTypeMethod(mat, setunfactored);
8171   PetscFunctionReturn(PETSC_SUCCESS);
8172 }
8173 
8174 /*MC
8175     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8176 
8177     Synopsis:
8178     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8179 
8180     Not Collective
8181 
8182     Input Parameter:
8183 .   x - matrix
8184 
8185     Output Parameters:
8186 +   xx_v - the Fortran pointer to the array
8187 -   ierr - error code
8188 
8189     Example of Usage:
8190 .vb
8191       PetscScalar, pointer xx_v(:,:)
8192       ....
8193       call MatDenseGetArrayF90(x,xx_v,ierr)
8194       a = xx_v(3)
8195       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8196 .ve
8197 
8198     Level: advanced
8199 
8200 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8201 M*/
8202 
8203 /*MC
8204     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8205     accessed with `MatDenseGetArrayF90()`.
8206 
8207     Synopsis:
8208     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8209 
8210     Not Collective
8211 
8212     Input Parameters:
8213 +   x - matrix
8214 -   xx_v - the Fortran90 pointer to the array
8215 
8216     Output Parameter:
8217 .   ierr - error code
8218 
8219     Example of Usage:
8220 .vb
8221        PetscScalar, pointer xx_v(:,:)
8222        ....
8223        call MatDenseGetArrayF90(x,xx_v,ierr)
8224        a = xx_v(3)
8225        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8226 .ve
8227 
8228     Level: advanced
8229 
8230 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8231 M*/
8232 
8233 /*MC
8234     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8235 
8236     Synopsis:
8237     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8238 
8239     Not Collective
8240 
8241     Input Parameter:
8242 .   x - matrix
8243 
8244     Output Parameters:
8245 +   xx_v - the Fortran pointer to the array
8246 -   ierr - error code
8247 
8248     Example of Usage:
8249 .vb
8250       PetscScalar, pointer xx_v(:)
8251       ....
8252       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8253       a = xx_v(3)
8254       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8255 .ve
8256 
8257     Level: advanced
8258 
8259 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8260 M*/
8261 
8262 /*MC
8263     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8264     accessed with `MatSeqAIJGetArrayF90()`.
8265 
8266     Synopsis:
8267     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8268 
8269     Not Collective
8270 
8271     Input Parameters:
8272 +   x - matrix
8273 -   xx_v - the Fortran90 pointer to the array
8274 
8275     Output Parameter:
8276 .   ierr - error code
8277 
8278     Example of Usage:
8279 .vb
8280        PetscScalar, pointer xx_v(:)
8281        ....
8282        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8283        a = xx_v(3)
8284        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8285 .ve
8286 
8287     Level: advanced
8288 
8289 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8290 M*/
8291 
8292 /*@
8293     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8294                       as the original matrix.
8295 
8296     Collective
8297 
8298     Input Parameters:
8299 +   mat - the original matrix
8300 .   isrow - parallel `IS` containing the rows this processor should obtain
8301 .   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.
8302 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8303 
8304     Output Parameter:
8305 .   newmat - the new submatrix, of the same type as the original matrix
8306 
8307     Level: advanced
8308 
8309     Notes:
8310     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8311 
8312     Some matrix types place restrictions on the row and column indices, such
8313     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;
8314     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8315 
8316     The index sets may not have duplicate entries.
8317 
8318       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8319    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8320    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8321    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8322    you are finished using it.
8323 
8324     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8325     the input matrix.
8326 
8327     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8328 
8329    Example usage:
8330    Consider the following 8x8 matrix with 34 non-zero values, that is
8331    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8332    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8333    as follows
8334 .vb
8335             1  2  0  |  0  3  0  |  0  4
8336     Proc0   0  5  6  |  7  0  0  |  8  0
8337             9  0 10  | 11  0  0  | 12  0
8338     -------------------------------------
8339            13  0 14  | 15 16 17  |  0  0
8340     Proc1   0 18  0  | 19 20 21  |  0  0
8341             0  0  0  | 22 23  0  | 24  0
8342     -------------------------------------
8343     Proc2  25 26 27  |  0  0 28  | 29  0
8344            30  0  0  | 31 32 33  |  0 34
8345 .ve
8346 
8347     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8348 
8349 .vb
8350             2  0  |  0  3  0  |  0
8351     Proc0   5  6  |  7  0  0  |  8
8352     -------------------------------
8353     Proc1  18  0  | 19 20 21  |  0
8354     -------------------------------
8355     Proc2  26 27  |  0  0 28  | 29
8356             0  0  | 31 32 33  |  0
8357 .ve
8358 
8359 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8360 @*/
8361 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8362 {
8363   PetscMPIInt size;
8364   Mat        *local;
8365   IS          iscoltmp;
8366   PetscBool   flg;
8367 
8368   PetscFunctionBegin;
8369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8370   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8371   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8372   PetscValidPointer(newmat, 5);
8373   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8374   PetscValidType(mat, 1);
8375   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8376   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8377 
8378   MatCheckPreallocated(mat, 1);
8379   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8380 
8381   if (!iscol || isrow == iscol) {
8382     PetscBool   stride;
8383     PetscMPIInt grabentirematrix = 0, grab;
8384     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8385     if (stride) {
8386       PetscInt first, step, n, rstart, rend;
8387       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8388       if (step == 1) {
8389         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8390         if (rstart == first) {
8391           PetscCall(ISGetLocalSize(isrow, &n));
8392           if (n == rend - rstart) grabentirematrix = 1;
8393         }
8394       }
8395     }
8396     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8397     if (grab) {
8398       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8399       if (cll == MAT_INITIAL_MATRIX) {
8400         *newmat = mat;
8401         PetscCall(PetscObjectReference((PetscObject)mat));
8402       }
8403       PetscFunctionReturn(PETSC_SUCCESS);
8404     }
8405   }
8406 
8407   if (!iscol) {
8408     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8409   } else {
8410     iscoltmp = iscol;
8411   }
8412 
8413   /* if original matrix is on just one processor then use submatrix generated */
8414   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8415     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8416     goto setproperties;
8417   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8418     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8419     *newmat = *local;
8420     PetscCall(PetscFree(local));
8421     goto setproperties;
8422   } else if (!mat->ops->createsubmatrix) {
8423     /* Create a new matrix type that implements the operation using the full matrix */
8424     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8425     switch (cll) {
8426     case MAT_INITIAL_MATRIX:
8427       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8428       break;
8429     case MAT_REUSE_MATRIX:
8430       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8431       break;
8432     default:
8433       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8434     }
8435     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8436     goto setproperties;
8437   }
8438 
8439   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8440   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8441   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8442 
8443 setproperties:
8444   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8445   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8446   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8447   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8448   PetscFunctionReturn(PETSC_SUCCESS);
8449 }
8450 
8451 /*@
8452    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8453 
8454    Not Collective
8455 
8456    Input Parameters:
8457 +  A - the matrix we wish to propagate options from
8458 -  B - the matrix we wish to propagate options to
8459 
8460    Level: beginner
8461 
8462    Note:
8463    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8464 
8465 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8466 @*/
8467 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8468 {
8469   PetscFunctionBegin;
8470   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8471   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8472   B->symmetry_eternal            = A->symmetry_eternal;
8473   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8474   B->symmetric                   = A->symmetric;
8475   B->structurally_symmetric      = A->structurally_symmetric;
8476   B->spd                         = A->spd;
8477   B->hermitian                   = A->hermitian;
8478   PetscFunctionReturn(PETSC_SUCCESS);
8479 }
8480 
8481 /*@
8482    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8483    used during the assembly process to store values that belong to
8484    other processors.
8485 
8486    Not Collective
8487 
8488    Input Parameters:
8489 +  mat   - the matrix
8490 .  size  - the initial size of the stash.
8491 -  bsize - the initial size of the block-stash(if used).
8492 
8493    Options Database Keys:
8494 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8495 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8496 
8497    Level: intermediate
8498 
8499    Notes:
8500      The block-stash is used for values set with `MatSetValuesBlocked()` while
8501      the stash is used for values set with `MatSetValues()`
8502 
8503      Run with the option -info and look for output of the form
8504      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8505      to determine the appropriate value, MM, to use for size and
8506      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8507      to determine the value, BMM to use for bsize
8508 
8509 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8510 @*/
8511 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8512 {
8513   PetscFunctionBegin;
8514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8515   PetscValidType(mat, 1);
8516   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8517   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8518   PetscFunctionReturn(PETSC_SUCCESS);
8519 }
8520 
8521 /*@
8522    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8523      the matrix
8524 
8525    Neighbor-wise Collective
8526 
8527    Input Parameters:
8528 +  mat   - the matrix
8529 .  x - the vector to be multiplied by the interpolation operator
8530 -  y - the vector to be added to the result
8531 
8532    Output Parameter:
8533 .  w - the resulting vector
8534 
8535    Level: intermediate
8536 
8537    Notes:
8538     `w` may be the same vector as `y`.
8539 
8540     This allows one to use either the restriction or interpolation (its transpose)
8541     matrix to do the interpolation
8542 
8543 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8544 @*/
8545 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8546 {
8547   PetscInt M, N, Ny;
8548 
8549   PetscFunctionBegin;
8550   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8551   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8552   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8553   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8554   PetscCall(MatGetSize(A, &M, &N));
8555   PetscCall(VecGetSize(y, &Ny));
8556   if (M == Ny) {
8557     PetscCall(MatMultAdd(A, x, y, w));
8558   } else {
8559     PetscCall(MatMultTransposeAdd(A, x, y, w));
8560   }
8561   PetscFunctionReturn(PETSC_SUCCESS);
8562 }
8563 
8564 /*@
8565    MatInterpolate - y = A*x or A'*x depending on the shape of
8566      the matrix
8567 
8568    Neighbor-wise Collective
8569 
8570    Input Parameters:
8571 +  mat   - the matrix
8572 -  x - the vector to be interpolated
8573 
8574    Output Parameter:
8575 .  y - the resulting vector
8576 
8577    Level: intermediate
8578 
8579    Note:
8580     This allows one to use either the restriction or interpolation (its transpose)
8581     matrix to do the interpolation
8582 
8583 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8584 @*/
8585 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8586 {
8587   PetscInt M, N, Ny;
8588 
8589   PetscFunctionBegin;
8590   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8591   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8592   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8593   PetscCall(MatGetSize(A, &M, &N));
8594   PetscCall(VecGetSize(y, &Ny));
8595   if (M == Ny) {
8596     PetscCall(MatMult(A, x, y));
8597   } else {
8598     PetscCall(MatMultTranspose(A, x, y));
8599   }
8600   PetscFunctionReturn(PETSC_SUCCESS);
8601 }
8602 
8603 /*@
8604    MatRestrict - y = A*x or A'*x
8605 
8606    Neighbor-wise Collective
8607 
8608    Input Parameters:
8609 +  mat   - the matrix
8610 -  x - the vector to be restricted
8611 
8612    Output Parameter:
8613 .  y - the resulting vector
8614 
8615    Level: intermediate
8616 
8617    Note:
8618     This allows one to use either the restriction or interpolation (its transpose)
8619     matrix to do the restriction
8620 
8621 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8622 @*/
8623 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8624 {
8625   PetscInt M, N, Ny;
8626 
8627   PetscFunctionBegin;
8628   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8629   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8630   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8631   PetscCall(MatGetSize(A, &M, &N));
8632   PetscCall(VecGetSize(y, &Ny));
8633   if (M == Ny) {
8634     PetscCall(MatMult(A, x, y));
8635   } else {
8636     PetscCall(MatMultTranspose(A, x, y));
8637   }
8638   PetscFunctionReturn(PETSC_SUCCESS);
8639 }
8640 
8641 /*@
8642    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8643 
8644    Neighbor-wise Collective
8645 
8646    Input Parameters:
8647 +  mat   - the matrix
8648 .  x - the input dense matrix to be multiplied
8649 -  w - the input dense matrix to be added to the result
8650 
8651    Output Parameter:
8652 .  y - the output dense matrix
8653 
8654    Level: intermediate
8655 
8656    Note:
8657     This allows one to use either the restriction or interpolation (its transpose)
8658     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8659     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8660 
8661 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8662 @*/
8663 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8664 {
8665   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8666   PetscBool trans = PETSC_TRUE;
8667   MatReuse  reuse = MAT_INITIAL_MATRIX;
8668 
8669   PetscFunctionBegin;
8670   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8671   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8672   PetscValidType(x, 2);
8673   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8674   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8675   PetscCall(MatGetSize(A, &M, &N));
8676   PetscCall(MatGetSize(x, &Mx, &Nx));
8677   if (N == Mx) trans = PETSC_FALSE;
8678   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);
8679   Mo = trans ? N : M;
8680   if (*y) {
8681     PetscCall(MatGetSize(*y, &My, &Ny));
8682     if (Mo == My && Nx == Ny) {
8683       reuse = MAT_REUSE_MATRIX;
8684     } else {
8685       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);
8686       PetscCall(MatDestroy(y));
8687     }
8688   }
8689 
8690   if (w && *y == w) { /* this is to minimize changes in PCMG */
8691     PetscBool flg;
8692 
8693     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8694     if (w) {
8695       PetscInt My, Ny, Mw, Nw;
8696 
8697       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8698       PetscCall(MatGetSize(*y, &My, &Ny));
8699       PetscCall(MatGetSize(w, &Mw, &Nw));
8700       if (!flg || My != Mw || Ny != Nw) w = NULL;
8701     }
8702     if (!w) {
8703       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8704       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8705       PetscCall(PetscObjectDereference((PetscObject)w));
8706     } else {
8707       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8708     }
8709   }
8710   if (!trans) {
8711     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8712   } else {
8713     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8714   }
8715   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8716   PetscFunctionReturn(PETSC_SUCCESS);
8717 }
8718 
8719 /*@
8720    MatMatInterpolate - Y = A*X or A'*X
8721 
8722    Neighbor-wise Collective
8723 
8724    Input Parameters:
8725 +  mat   - the matrix
8726 -  x - the input dense matrix
8727 
8728    Output Parameter:
8729 .  y - the output dense matrix
8730 
8731    Level: intermediate
8732 
8733    Note:
8734     This allows one to use either the restriction or interpolation (its transpose)
8735     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8736     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8737 
8738 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8739 @*/
8740 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8741 {
8742   PetscFunctionBegin;
8743   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8744   PetscFunctionReturn(PETSC_SUCCESS);
8745 }
8746 
8747 /*@
8748    MatMatRestrict - Y = A*X or A'*X
8749 
8750    Neighbor-wise Collective
8751 
8752    Input Parameters:
8753 +  mat   - the matrix
8754 -  x - the input dense matrix
8755 
8756    Output Parameter:
8757 .  y - the output dense matrix
8758 
8759    Level: intermediate
8760 
8761    Note:
8762     This allows one to use either the restriction or interpolation (its transpose)
8763     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8764     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8765 
8766 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8767 @*/
8768 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8769 {
8770   PetscFunctionBegin;
8771   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8772   PetscFunctionReturn(PETSC_SUCCESS);
8773 }
8774 
8775 /*@
8776    MatGetNullSpace - retrieves the null space of a matrix.
8777 
8778    Logically Collective
8779 
8780    Input Parameters:
8781 +  mat - the matrix
8782 -  nullsp - the null space object
8783 
8784    Level: developer
8785 
8786 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8787 @*/
8788 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8789 {
8790   PetscFunctionBegin;
8791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8792   PetscValidPointer(nullsp, 2);
8793   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8794   PetscFunctionReturn(PETSC_SUCCESS);
8795 }
8796 
8797 /*@
8798    MatSetNullSpace - attaches a null space to a matrix.
8799 
8800    Logically Collective
8801 
8802    Input Parameters:
8803 +  mat - the matrix
8804 -  nullsp - the null space object
8805 
8806    Level: advanced
8807 
8808    Notes:
8809       This null space is used by the `KSP` linear solvers to solve singular systems.
8810 
8811       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`
8812 
8813       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
8814       to zero but the linear system will still be solved in a least squares sense.
8815 
8816       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8817    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).
8818    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
8819    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
8820    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).
8821    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8822 
8823     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8824     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8825     routine also automatically calls `MatSetTransposeNullSpace()`.
8826 
8827     The user should call `MatNullSpaceDestroy()`.
8828 
8829 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8830           `KSPSetPCSide()`
8831 @*/
8832 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8833 {
8834   PetscFunctionBegin;
8835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8836   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8837   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8838   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8839   mat->nullsp = nullsp;
8840   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8841   PetscFunctionReturn(PETSC_SUCCESS);
8842 }
8843 
8844 /*@
8845    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8846 
8847    Logically Collective
8848 
8849    Input Parameters:
8850 +  mat - the matrix
8851 -  nullsp - the null space object
8852 
8853    Level: developer
8854 
8855 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8856 @*/
8857 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8858 {
8859   PetscFunctionBegin;
8860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8861   PetscValidType(mat, 1);
8862   PetscValidPointer(nullsp, 2);
8863   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8864   PetscFunctionReturn(PETSC_SUCCESS);
8865 }
8866 
8867 /*@
8868    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8869 
8870    Logically Collective
8871 
8872    Input Parameters:
8873 +  mat - the matrix
8874 -  nullsp - the null space object
8875 
8876    Level: advanced
8877 
8878    Notes:
8879    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8880 
8881    See `MatSetNullSpace()`
8882 
8883 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8884 @*/
8885 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8886 {
8887   PetscFunctionBegin;
8888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8889   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8890   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8891   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8892   mat->transnullsp = nullsp;
8893   PetscFunctionReturn(PETSC_SUCCESS);
8894 }
8895 
8896 /*@
8897    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8898         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8899 
8900    Logically Collective
8901 
8902    Input Parameters:
8903 +  mat - the matrix
8904 -  nullsp - the null space object
8905 
8906    Level: advanced
8907 
8908    Notes:
8909    Overwrites any previous near null space that may have been attached
8910 
8911    You can remove the null space by calling this routine with an nullsp of `NULL`
8912 
8913 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8914 @*/
8915 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8916 {
8917   PetscFunctionBegin;
8918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8919   PetscValidType(mat, 1);
8920   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8921   MatCheckPreallocated(mat, 1);
8922   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8923   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8924   mat->nearnullsp = nullsp;
8925   PetscFunctionReturn(PETSC_SUCCESS);
8926 }
8927 
8928 /*@
8929    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8930 
8931    Not Collective
8932 
8933    Input Parameter:
8934 .  mat - the matrix
8935 
8936    Output Parameter:
8937 .  nullsp - the null space object, `NULL` if not set
8938 
8939    Level: advanced
8940 
8941 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8942 @*/
8943 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8944 {
8945   PetscFunctionBegin;
8946   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8947   PetscValidType(mat, 1);
8948   PetscValidPointer(nullsp, 2);
8949   MatCheckPreallocated(mat, 1);
8950   *nullsp = mat->nearnullsp;
8951   PetscFunctionReturn(PETSC_SUCCESS);
8952 }
8953 
8954 /*@C
8955    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8956 
8957    Collective
8958 
8959    Input Parameters:
8960 +  mat - the matrix
8961 .  row - row/column permutation
8962 -  info - information on desired factorization process
8963 
8964    Level: developer
8965 
8966    Notes:
8967    Probably really in-place only when level of fill is zero, otherwise allocates
8968    new space to store factored matrix and deletes previous memory.
8969 
8970    Most users should employ the `KSP` interface for linear solvers
8971    instead of working directly with matrix algebra routines such as this.
8972    See, e.g., `KSPCreate()`.
8973 
8974    Developer Note:
8975    The Fortran interface is not autogenerated as the
8976    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8977 
8978 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8979 @*/
8980 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8981 {
8982   PetscFunctionBegin;
8983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8984   PetscValidType(mat, 1);
8985   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8986   PetscValidPointer(info, 3);
8987   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8988   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8989   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8990   MatCheckPreallocated(mat, 1);
8991   PetscUseTypeMethod(mat, iccfactor, row, info);
8992   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8993   PetscFunctionReturn(PETSC_SUCCESS);
8994 }
8995 
8996 /*@
8997    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8998          ghosted ones.
8999 
9000    Not Collective
9001 
9002    Input Parameters:
9003 +  mat - the matrix
9004 -  diag - the diagonal values, including ghost ones
9005 
9006    Level: developer
9007 
9008    Notes:
9009     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9010 
9011     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9012 
9013 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9014 @*/
9015 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9016 {
9017   PetscMPIInt size;
9018 
9019   PetscFunctionBegin;
9020   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9021   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9022   PetscValidType(mat, 1);
9023 
9024   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9025   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9026   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9027   if (size == 1) {
9028     PetscInt n, m;
9029     PetscCall(VecGetSize(diag, &n));
9030     PetscCall(MatGetSize(mat, NULL, &m));
9031     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9032     PetscCall(MatDiagonalScale(mat, NULL, diag));
9033   } else {
9034     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9035   }
9036   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9037   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9038   PetscFunctionReturn(PETSC_SUCCESS);
9039 }
9040 
9041 /*@
9042    MatGetInertia - Gets the inertia from a factored matrix
9043 
9044    Collective
9045 
9046    Input Parameter:
9047 .  mat - the matrix
9048 
9049    Output Parameters:
9050 +   nneg - number of negative eigenvalues
9051 .   nzero - number of zero eigenvalues
9052 -   npos - number of positive eigenvalues
9053 
9054    Level: advanced
9055 
9056    Note:
9057     Matrix must have been factored by `MatCholeskyFactor()`
9058 
9059 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9060 @*/
9061 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9062 {
9063   PetscFunctionBegin;
9064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9065   PetscValidType(mat, 1);
9066   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9067   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9068   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9069   PetscFunctionReturn(PETSC_SUCCESS);
9070 }
9071 
9072 /*@C
9073    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9074 
9075    Neighbor-wise Collective
9076 
9077    Input Parameters:
9078 +  mat - the factored matrix obtained with `MatGetFactor()`
9079 -  b - the right-hand-side vectors
9080 
9081    Output Parameter:
9082 .  x - the result vectors
9083 
9084    Level: developer
9085 
9086    Note:
9087    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9088    call `MatSolves`(A,x,x).
9089 
9090 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9091 @*/
9092 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9093 {
9094   PetscFunctionBegin;
9095   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9096   PetscValidType(mat, 1);
9097   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9098   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9099   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9100 
9101   MatCheckPreallocated(mat, 1);
9102   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9103   PetscUseTypeMethod(mat, solves, b, x);
9104   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9105   PetscFunctionReturn(PETSC_SUCCESS);
9106 }
9107 
9108 /*@
9109    MatIsSymmetric - Test whether a matrix is symmetric
9110 
9111    Collective
9112 
9113    Input Parameters:
9114 +  A - the matrix to test
9115 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9116 
9117    Output Parameter:
9118 .  flg - the result
9119 
9120    Level: intermediate
9121 
9122    Notes:
9123     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9124 
9125     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9126 
9127     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9128     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9129 
9130 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9131           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9132 @*/
9133 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9134 {
9135   PetscFunctionBegin;
9136   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9137   PetscValidBoolPointer(flg, 3);
9138 
9139   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9140   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9141   else {
9142     PetscUseTypeMethod(A, issymmetric, tol, flg);
9143     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9144   }
9145   PetscFunctionReturn(PETSC_SUCCESS);
9146 }
9147 
9148 /*@
9149    MatIsHermitian - Test whether a matrix is Hermitian
9150 
9151    Collective
9152 
9153    Input Parameters:
9154 +  A - the matrix to test
9155 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9156 
9157    Output Parameter:
9158 .  flg - the result
9159 
9160    Level: intermediate
9161 
9162    Notes:
9163     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9164 
9165     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9166 
9167     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9168     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9169 
9170 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9171           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9172 @*/
9173 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9174 {
9175   PetscFunctionBegin;
9176   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9177   PetscValidBoolPointer(flg, 3);
9178 
9179   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9180   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9181   else {
9182     PetscUseTypeMethod(A, ishermitian, tol, flg);
9183     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9184   }
9185   PetscFunctionReturn(PETSC_SUCCESS);
9186 }
9187 
9188 /*@
9189    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9190 
9191    Not Collective
9192 
9193    Input Parameter:
9194 .  A - the matrix to check
9195 
9196    Output Parameters:
9197 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9198 -  flg - the result (only valid if set is `PETSC_TRUE`)
9199 
9200    Level: advanced
9201 
9202    Notes:
9203    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9204    if you want it explicitly checked
9205 
9206     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9207     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9208 
9209 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9210 @*/
9211 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9212 {
9213   PetscFunctionBegin;
9214   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9215   PetscValidBoolPointer(set, 2);
9216   PetscValidBoolPointer(flg, 3);
9217   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9218     *set = PETSC_TRUE;
9219     *flg = PetscBool3ToBool(A->symmetric);
9220   } else {
9221     *set = PETSC_FALSE;
9222   }
9223   PetscFunctionReturn(PETSC_SUCCESS);
9224 }
9225 
9226 /*@
9227    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9228 
9229    Not Collective
9230 
9231    Input Parameter:
9232 .  A - the matrix to check
9233 
9234    Output Parameters:
9235 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9236 -  flg - the result (only valid if set is `PETSC_TRUE`)
9237 
9238    Level: advanced
9239 
9240    Notes:
9241    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9242 
9243    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9244    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9245 
9246 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9247 @*/
9248 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9249 {
9250   PetscFunctionBegin;
9251   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9252   PetscValidBoolPointer(set, 2);
9253   PetscValidBoolPointer(flg, 3);
9254   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9255     *set = PETSC_TRUE;
9256     *flg = PetscBool3ToBool(A->spd);
9257   } else {
9258     *set = PETSC_FALSE;
9259   }
9260   PetscFunctionReturn(PETSC_SUCCESS);
9261 }
9262 
9263 /*@
9264    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9265 
9266    Not Collective
9267 
9268    Input Parameter:
9269 .  A - the matrix to check
9270 
9271    Output Parameters:
9272 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9273 -  flg - the result (only valid if set is `PETSC_TRUE`)
9274 
9275    Level: advanced
9276 
9277    Notes:
9278    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9279    if you want it explicitly checked
9280 
9281    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9282    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9283 
9284 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9285 @*/
9286 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9287 {
9288   PetscFunctionBegin;
9289   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9290   PetscValidBoolPointer(set, 2);
9291   PetscValidBoolPointer(flg, 3);
9292   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9293     *set = PETSC_TRUE;
9294     *flg = PetscBool3ToBool(A->hermitian);
9295   } else {
9296     *set = PETSC_FALSE;
9297   }
9298   PetscFunctionReturn(PETSC_SUCCESS);
9299 }
9300 
9301 /*@
9302    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9303 
9304    Collective
9305 
9306    Input Parameter:
9307 .  A - the matrix to test
9308 
9309    Output Parameter:
9310 .  flg - the result
9311 
9312    Level: intermediate
9313 
9314    Notes:
9315    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9316 
9317    One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9318    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9319 
9320 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9321 @*/
9322 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9323 {
9324   PetscFunctionBegin;
9325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9326   PetscValidBoolPointer(flg, 2);
9327   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9328     *flg = PetscBool3ToBool(A->structurally_symmetric);
9329   } else {
9330     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9331     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9332   }
9333   PetscFunctionReturn(PETSC_SUCCESS);
9334 }
9335 
9336 /*@
9337    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9338 
9339    Not Collective
9340 
9341    Input Parameter:
9342 .  A - the matrix to check
9343 
9344    Output Parameters:
9345 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9346 -  flg - the result (only valid if set is PETSC_TRUE)
9347 
9348    Level: advanced
9349 
9350    Notes:
9351    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
9352    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9353 
9354    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9355 
9356 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9357 @*/
9358 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9359 {
9360   PetscFunctionBegin;
9361   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9362   PetscValidBoolPointer(set, 2);
9363   PetscValidBoolPointer(flg, 3);
9364   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9365     *set = PETSC_TRUE;
9366     *flg = PetscBool3ToBool(A->structurally_symmetric);
9367   } else {
9368     *set = PETSC_FALSE;
9369   }
9370   PetscFunctionReturn(PETSC_SUCCESS);
9371 }
9372 
9373 /*@
9374    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9375        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9376 
9377     Not Collective
9378 
9379    Input Parameter:
9380 .   mat - the matrix
9381 
9382    Output Parameters:
9383 +   nstash   - the size of the stash
9384 .   reallocs - the number of additional mallocs incurred.
9385 .   bnstash   - the size of the block stash
9386 -   breallocs - the number of additional mallocs incurred.in the block stash
9387 
9388    Level: advanced
9389 
9390 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9391 @*/
9392 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9393 {
9394   PetscFunctionBegin;
9395   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9396   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9397   PetscFunctionReturn(PETSC_SUCCESS);
9398 }
9399 
9400 /*@C
9401    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9402    parallel layout, `PetscLayout` for rows and columns
9403 
9404    Collective
9405 
9406    Input Parameter:
9407 .  mat - the matrix
9408 
9409    Output Parameters:
9410 +   right - (optional) vector that the matrix can be multiplied against
9411 -   left - (optional) vector that the matrix vector product can be stored in
9412 
9413   Level: advanced
9414 
9415    Notes:
9416     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()`.
9417 
9418     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9419 
9420 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9421 @*/
9422 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9423 {
9424   PetscFunctionBegin;
9425   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9426   PetscValidType(mat, 1);
9427   if (mat->ops->getvecs) {
9428     PetscUseTypeMethod(mat, getvecs, right, left);
9429   } else {
9430     PetscInt rbs, cbs;
9431     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9432     if (right) {
9433       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9434       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9435       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9436       PetscCall(VecSetBlockSize(*right, cbs));
9437       PetscCall(VecSetType(*right, mat->defaultvectype));
9438 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9439       if (mat->boundtocpu && mat->bindingpropagates) {
9440         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9441         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9442       }
9443 #endif
9444       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9445     }
9446     if (left) {
9447       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9448       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9449       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9450       PetscCall(VecSetBlockSize(*left, rbs));
9451       PetscCall(VecSetType(*left, mat->defaultvectype));
9452 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9453       if (mat->boundtocpu && mat->bindingpropagates) {
9454         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9455         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9456       }
9457 #endif
9458       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9459     }
9460   }
9461   PetscFunctionReturn(PETSC_SUCCESS);
9462 }
9463 
9464 /*@C
9465    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9466      with default values.
9467 
9468    Not Collective
9469 
9470    Input Parameter:
9471 .    info - the `MatFactorInfo` data structure
9472 
9473    Level: developer
9474 
9475    Notes:
9476     The solvers are generally used through the `KSP` and `PC` objects, for example
9477           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9478 
9479     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9480 
9481    Developer Note:
9482    The Fortran interface is not autogenerated as the
9483    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9484 
9485 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9486 @*/
9487 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9488 {
9489   PetscFunctionBegin;
9490   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9491   PetscFunctionReturn(PETSC_SUCCESS);
9492 }
9493 
9494 /*@
9495    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9496 
9497    Collective
9498 
9499    Input Parameters:
9500 +  mat - the factored matrix
9501 -  is - the index set defining the Schur indices (0-based)
9502 
9503    Level: advanced
9504 
9505    Notes:
9506     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9507 
9508    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9509 
9510    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9511 
9512 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9513           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9514 @*/
9515 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9516 {
9517   PetscErrorCode (*f)(Mat, IS);
9518 
9519   PetscFunctionBegin;
9520   PetscValidType(mat, 1);
9521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9522   PetscValidType(is, 2);
9523   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9524   PetscCheckSameComm(mat, 1, is, 2);
9525   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9526   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9527   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9528   PetscCall(MatDestroy(&mat->schur));
9529   PetscCall((*f)(mat, is));
9530   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9531   PetscFunctionReturn(PETSC_SUCCESS);
9532 }
9533 
9534 /*@
9535   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9536 
9537    Logically Collective
9538 
9539    Input Parameters:
9540 +  F - the factored matrix obtained by calling `MatGetFactor()`
9541 .  S - location where to return the Schur complement, can be `NULL`
9542 -  status - the status of the Schur complement matrix, can be `NULL`
9543 
9544    Level: advanced
9545 
9546    Notes:
9547    You must call `MatFactorSetSchurIS()` before calling this routine.
9548 
9549    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9550 
9551    The routine provides a copy of the Schur matrix stored within the solver data structures.
9552    The caller must destroy the object when it is no longer needed.
9553    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9554 
9555    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)
9556 
9557    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9558 
9559    Developer Note:
9560     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9561    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9562 
9563 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9564 @*/
9565 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9566 {
9567   PetscFunctionBegin;
9568   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9569   if (S) PetscValidPointer(S, 2);
9570   if (status) PetscValidPointer(status, 3);
9571   if (S) {
9572     PetscErrorCode (*f)(Mat, Mat *);
9573 
9574     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9575     if (f) {
9576       PetscCall((*f)(F, S));
9577     } else {
9578       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9579     }
9580   }
9581   if (status) *status = F->schur_status;
9582   PetscFunctionReturn(PETSC_SUCCESS);
9583 }
9584 
9585 /*@
9586   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9587 
9588    Logically Collective
9589 
9590    Input Parameters:
9591 +  F - the factored matrix obtained by calling `MatGetFactor()`
9592 .  *S - location where to return the Schur complement, can be `NULL`
9593 -  status - the status of the Schur complement matrix, can be `NULL`
9594 
9595    Level: advanced
9596 
9597    Notes:
9598    You must call `MatFactorSetSchurIS()` before calling this routine.
9599 
9600    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9601 
9602    The routine returns a the Schur Complement stored within the data structures of the solver.
9603 
9604    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9605 
9606    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9607 
9608    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9609 
9610    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9611 
9612 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9613 @*/
9614 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9615 {
9616   PetscFunctionBegin;
9617   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9618   if (S) PetscValidPointer(S, 2);
9619   if (status) PetscValidPointer(status, 3);
9620   if (S) *S = F->schur;
9621   if (status) *status = F->schur_status;
9622   PetscFunctionReturn(PETSC_SUCCESS);
9623 }
9624 
9625 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9626 {
9627   Mat S = F->schur;
9628 
9629   PetscFunctionBegin;
9630   switch (F->schur_status) {
9631   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9632   case MAT_FACTOR_SCHUR_INVERTED:
9633     if (S) {
9634       S->ops->solve             = NULL;
9635       S->ops->matsolve          = NULL;
9636       S->ops->solvetranspose    = NULL;
9637       S->ops->matsolvetranspose = NULL;
9638       S->ops->solveadd          = NULL;
9639       S->ops->solvetransposeadd = NULL;
9640       S->factortype             = MAT_FACTOR_NONE;
9641       PetscCall(PetscFree(S->solvertype));
9642     }
9643   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9644     break;
9645   default:
9646     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9647   }
9648   PetscFunctionReturn(PETSC_SUCCESS);
9649 }
9650 
9651 /*@
9652   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9653 
9654    Logically Collective
9655 
9656    Input Parameters:
9657 +  F - the factored matrix obtained by calling `MatGetFactor()`
9658 .  *S - location where the Schur complement is stored
9659 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9660 
9661    Level: advanced
9662 
9663 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9664 @*/
9665 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9666 {
9667   PetscFunctionBegin;
9668   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9669   if (S) {
9670     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9671     *S = NULL;
9672   }
9673   F->schur_status = status;
9674   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9675   PetscFunctionReturn(PETSC_SUCCESS);
9676 }
9677 
9678 /*@
9679   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9680 
9681    Logically Collective
9682 
9683    Input Parameters:
9684 +  F - the factored matrix obtained by calling `MatGetFactor()`
9685 .  rhs - location where the right hand side of the Schur complement system is stored
9686 -  sol - location where the solution of the Schur complement system has to be returned
9687 
9688    Level: advanced
9689 
9690    Notes:
9691    The sizes of the vectors should match the size of the Schur complement
9692 
9693    Must be called after `MatFactorSetSchurIS()`
9694 
9695 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9696 @*/
9697 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9698 {
9699   PetscFunctionBegin;
9700   PetscValidType(F, 1);
9701   PetscValidType(rhs, 2);
9702   PetscValidType(sol, 3);
9703   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9704   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9705   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9706   PetscCheckSameComm(F, 1, rhs, 2);
9707   PetscCheckSameComm(F, 1, sol, 3);
9708   PetscCall(MatFactorFactorizeSchurComplement(F));
9709   switch (F->schur_status) {
9710   case MAT_FACTOR_SCHUR_FACTORED:
9711     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9712     break;
9713   case MAT_FACTOR_SCHUR_INVERTED:
9714     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9715     break;
9716   default:
9717     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9718   }
9719   PetscFunctionReturn(PETSC_SUCCESS);
9720 }
9721 
9722 /*@
9723   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9724 
9725    Logically Collective
9726 
9727    Input Parameters:
9728 +  F - the factored matrix obtained by calling `MatGetFactor()`
9729 .  rhs - location where the right hand side of the Schur complement system is stored
9730 -  sol - location where the solution of the Schur complement system has to be returned
9731 
9732    Level: advanced
9733 
9734    Notes:
9735    The sizes of the vectors should match the size of the Schur complement
9736 
9737    Must be called after `MatFactorSetSchurIS()`
9738 
9739 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9740 @*/
9741 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9742 {
9743   PetscFunctionBegin;
9744   PetscValidType(F, 1);
9745   PetscValidType(rhs, 2);
9746   PetscValidType(sol, 3);
9747   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9748   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9749   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9750   PetscCheckSameComm(F, 1, rhs, 2);
9751   PetscCheckSameComm(F, 1, sol, 3);
9752   PetscCall(MatFactorFactorizeSchurComplement(F));
9753   switch (F->schur_status) {
9754   case MAT_FACTOR_SCHUR_FACTORED:
9755     PetscCall(MatSolve(F->schur, rhs, sol));
9756     break;
9757   case MAT_FACTOR_SCHUR_INVERTED:
9758     PetscCall(MatMult(F->schur, rhs, sol));
9759     break;
9760   default:
9761     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9762   }
9763   PetscFunctionReturn(PETSC_SUCCESS);
9764 }
9765 
9766 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9767 #if PetscDefined(HAVE_CUDA)
9768 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9769 #endif
9770 
9771 /* Schur status updated in the interface */
9772 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9773 {
9774   Mat S = F->schur;
9775 
9776   PetscFunctionBegin;
9777   if (S) {
9778     PetscMPIInt size;
9779     PetscBool   isdense, isdensecuda;
9780 
9781     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9782     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9783     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9784     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9785     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9786     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9787     if (isdense) {
9788       PetscCall(MatSeqDenseInvertFactors_Private(S));
9789     } else if (isdensecuda) {
9790 #if defined(PETSC_HAVE_CUDA)
9791       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9792 #endif
9793     }
9794     // HIP??????????????
9795     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9796   }
9797   PetscFunctionReturn(PETSC_SUCCESS);
9798 }
9799 
9800 /*@
9801   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9802 
9803    Logically Collective
9804 
9805    Input Parameter:
9806 .  F - the factored matrix obtained by calling `MatGetFactor()`
9807 
9808    Level: advanced
9809 
9810    Notes:
9811     Must be called after `MatFactorSetSchurIS()`.
9812 
9813    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9814 
9815 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9816 @*/
9817 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9818 {
9819   PetscFunctionBegin;
9820   PetscValidType(F, 1);
9821   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9822   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9823   PetscCall(MatFactorFactorizeSchurComplement(F));
9824   PetscCall(MatFactorInvertSchurComplement_Private(F));
9825   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9826   PetscFunctionReturn(PETSC_SUCCESS);
9827 }
9828 
9829 /*@
9830   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9831 
9832    Logically Collective
9833 
9834    Input Parameter:
9835 .  F - the factored matrix obtained by calling `MatGetFactor()`
9836 
9837    Level: advanced
9838 
9839    Note:
9840     Must be called after `MatFactorSetSchurIS()`
9841 
9842 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9843 @*/
9844 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9845 {
9846   MatFactorInfo info;
9847 
9848   PetscFunctionBegin;
9849   PetscValidType(F, 1);
9850   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9851   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9852   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9853   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9854   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9855     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9856   } else {
9857     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9858   }
9859   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9860   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9861   PetscFunctionReturn(PETSC_SUCCESS);
9862 }
9863 
9864 /*@
9865    MatPtAP - Creates the matrix product C = P^T * A * P
9866 
9867    Neighbor-wise Collective
9868 
9869    Input Parameters:
9870 +  A - the matrix
9871 .  P - the projection matrix
9872 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9873 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9874           if the result is a dense matrix this is irrelevant
9875 
9876    Output Parameter:
9877 .  C - the product matrix
9878 
9879    Level: intermediate
9880 
9881    Notes:
9882    C will be created and must be destroyed by the user with `MatDestroy()`.
9883 
9884    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9885 
9886    Developer Note:
9887    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9888 
9889 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9890 @*/
9891 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9892 {
9893   PetscFunctionBegin;
9894   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9895   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9896 
9897   if (scall == MAT_INITIAL_MATRIX) {
9898     PetscCall(MatProductCreate(A, P, NULL, C));
9899     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9900     PetscCall(MatProductSetAlgorithm(*C, "default"));
9901     PetscCall(MatProductSetFill(*C, fill));
9902 
9903     (*C)->product->api_user = PETSC_TRUE;
9904     PetscCall(MatProductSetFromOptions(*C));
9905     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);
9906     PetscCall(MatProductSymbolic(*C));
9907   } else { /* scall == MAT_REUSE_MATRIX */
9908     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9909   }
9910 
9911   PetscCall(MatProductNumeric(*C));
9912   (*C)->symmetric = A->symmetric;
9913   (*C)->spd       = A->spd;
9914   PetscFunctionReturn(PETSC_SUCCESS);
9915 }
9916 
9917 /*@
9918    MatRARt - Creates the matrix product C = R * A * R^T
9919 
9920    Neighbor-wise Collective
9921 
9922    Input Parameters:
9923 +  A - the matrix
9924 .  R - the projection matrix
9925 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9926 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9927           if the result is a dense matrix this is irrelevant
9928 
9929    Output Parameter:
9930 .  C - the product matrix
9931 
9932    Level: intermediate
9933 
9934    Notes:
9935    C will be created and must be destroyed by the user with `MatDestroy()`.
9936 
9937    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9938 
9939    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9940    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9941    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9942    We recommend using MatPtAP().
9943 
9944 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9945 @*/
9946 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9947 {
9948   PetscFunctionBegin;
9949   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9950   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9951 
9952   if (scall == MAT_INITIAL_MATRIX) {
9953     PetscCall(MatProductCreate(A, R, NULL, C));
9954     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9955     PetscCall(MatProductSetAlgorithm(*C, "default"));
9956     PetscCall(MatProductSetFill(*C, fill));
9957 
9958     (*C)->product->api_user = PETSC_TRUE;
9959     PetscCall(MatProductSetFromOptions(*C));
9960     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);
9961     PetscCall(MatProductSymbolic(*C));
9962   } else { /* scall == MAT_REUSE_MATRIX */
9963     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9964   }
9965 
9966   PetscCall(MatProductNumeric(*C));
9967   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9968   PetscFunctionReturn(PETSC_SUCCESS);
9969 }
9970 
9971 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9972 {
9973   PetscFunctionBegin;
9974   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9975 
9976   if (scall == MAT_INITIAL_MATRIX) {
9977     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9978     PetscCall(MatProductCreate(A, B, NULL, C));
9979     PetscCall(MatProductSetType(*C, ptype));
9980     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9981     PetscCall(MatProductSetFill(*C, fill));
9982 
9983     (*C)->product->api_user = PETSC_TRUE;
9984     PetscCall(MatProductSetFromOptions(*C));
9985     PetscCall(MatProductSymbolic(*C));
9986   } else { /* scall == MAT_REUSE_MATRIX */
9987     Mat_Product *product = (*C)->product;
9988     PetscBool    isdense;
9989 
9990     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9991     if (isdense && product && product->type != ptype) {
9992       PetscCall(MatProductClear(*C));
9993       product = NULL;
9994     }
9995     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9996     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9997       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9998       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9999       product           = (*C)->product;
10000       product->fill     = fill;
10001       product->api_user = PETSC_TRUE;
10002       product->clear    = PETSC_TRUE;
10003 
10004       PetscCall(MatProductSetType(*C, ptype));
10005       PetscCall(MatProductSetFromOptions(*C));
10006       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);
10007       PetscCall(MatProductSymbolic(*C));
10008     } else { /* user may change input matrices A or B when REUSE */
10009       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10010     }
10011   }
10012   PetscCall(MatProductNumeric(*C));
10013   PetscFunctionReturn(PETSC_SUCCESS);
10014 }
10015 
10016 /*@
10017    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10018 
10019    Neighbor-wise Collective
10020 
10021    Input Parameters:
10022 +  A - the left matrix
10023 .  B - the right matrix
10024 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10025 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10026           if the result is a dense matrix this is irrelevant
10027 
10028    Output Parameter:
10029 .  C - the product matrix
10030 
10031    Notes:
10032    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10033 
10034    `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
10035    call to this function with `MAT_INITIAL_MATRIX`.
10036 
10037    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10038 
10039    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`,
10040    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10041 
10042    Example of Usage:
10043 .vb
10044      MatProductCreate(A,B,NULL,&C);
10045      MatProductSetType(C,MATPRODUCT_AB);
10046      MatProductSymbolic(C);
10047      MatProductNumeric(C); // compute C=A * B
10048      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10049      MatProductNumeric(C);
10050      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10051      MatProductNumeric(C);
10052 .ve
10053 
10054    Level: intermediate
10055 
10056 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10057 @*/
10058 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10059 {
10060   PetscFunctionBegin;
10061   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10062   PetscFunctionReturn(PETSC_SUCCESS);
10063 }
10064 
10065 /*@
10066    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10067 
10068    Neighbor-wise Collective
10069 
10070    Input Parameters:
10071 +  A - the left matrix
10072 .  B - the right matrix
10073 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10074 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10075 
10076    Output Parameter:
10077 .  C - the product matrix
10078 
10079    Level: intermediate
10080 
10081    Notes:
10082    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10083 
10084    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10085 
10086    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10087    actually needed.
10088 
10089    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10090    and for pairs of `MATMPIDENSE` matrices.
10091 
10092    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10093 
10094    Options Database Keys:
10095 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10096               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10097               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10098 
10099 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10100 @*/
10101 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10102 {
10103   PetscFunctionBegin;
10104   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10105   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10106   PetscFunctionReturn(PETSC_SUCCESS);
10107 }
10108 
10109 /*@
10110    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10111 
10112    Neighbor-wise Collective
10113 
10114    Input Parameters:
10115 +  A - the left matrix
10116 .  B - the right matrix
10117 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10118 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10119 
10120    Output Parameter:
10121 .  C - the product matrix
10122 
10123    Level: intermediate
10124 
10125    Notes:
10126    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10127 
10128    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10129 
10130    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10131 
10132    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10133    actually needed.
10134 
10135    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10136    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10137 
10138 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10139 @*/
10140 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10141 {
10142   PetscFunctionBegin;
10143   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10144   PetscFunctionReturn(PETSC_SUCCESS);
10145 }
10146 
10147 /*@
10148    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10149 
10150    Neighbor-wise Collective
10151 
10152    Input Parameters:
10153 +  A - the left matrix
10154 .  B - the middle matrix
10155 .  C - the right matrix
10156 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10157 -  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
10158           if the result is a dense matrix this is irrelevant
10159 
10160    Output Parameter:
10161 .  D - the product matrix
10162 
10163    Level: intermediate
10164 
10165    Notes:
10166    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10167 
10168    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10169 
10170    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10171 
10172    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10173    actually needed.
10174 
10175    If you have many matrices with the same non-zero structure to multiply, you
10176    should use `MAT_REUSE_MATRIX` in all calls but the first
10177 
10178 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10179 @*/
10180 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10181 {
10182   PetscFunctionBegin;
10183   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10184   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10185 
10186   if (scall == MAT_INITIAL_MATRIX) {
10187     PetscCall(MatProductCreate(A, B, C, D));
10188     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10189     PetscCall(MatProductSetAlgorithm(*D, "default"));
10190     PetscCall(MatProductSetFill(*D, fill));
10191 
10192     (*D)->product->api_user = PETSC_TRUE;
10193     PetscCall(MatProductSetFromOptions(*D));
10194     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,
10195                ((PetscObject)C)->type_name);
10196     PetscCall(MatProductSymbolic(*D));
10197   } else { /* user may change input matrices when REUSE */
10198     PetscCall(MatProductReplaceMats(A, B, C, *D));
10199   }
10200   PetscCall(MatProductNumeric(*D));
10201   PetscFunctionReturn(PETSC_SUCCESS);
10202 }
10203 
10204 /*@
10205    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10206 
10207    Collective
10208 
10209    Input Parameters:
10210 +  mat - the matrix
10211 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10212 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10213 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10214 
10215    Output Parameter:
10216 .  matredundant - redundant matrix
10217 
10218    Level: advanced
10219 
10220    Notes:
10221    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10222    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10223 
10224    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10225    calling it.
10226 
10227    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10228 
10229 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10230 @*/
10231 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10232 {
10233   MPI_Comm       comm;
10234   PetscMPIInt    size;
10235   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10236   Mat_Redundant *redund     = NULL;
10237   PetscSubcomm   psubcomm   = NULL;
10238   MPI_Comm       subcomm_in = subcomm;
10239   Mat           *matseq;
10240   IS             isrow, iscol;
10241   PetscBool      newsubcomm = PETSC_FALSE;
10242 
10243   PetscFunctionBegin;
10244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10245   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10246     PetscValidPointer(*matredundant, 5);
10247     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10248   }
10249 
10250   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10251   if (size == 1 || nsubcomm == 1) {
10252     if (reuse == MAT_INITIAL_MATRIX) {
10253       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10254     } else {
10255       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");
10256       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10257     }
10258     PetscFunctionReturn(PETSC_SUCCESS);
10259   }
10260 
10261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10263   MatCheckPreallocated(mat, 1);
10264 
10265   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10266   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10267     /* create psubcomm, then get subcomm */
10268     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10269     PetscCallMPI(MPI_Comm_size(comm, &size));
10270     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10271 
10272     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10273     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10274     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10275     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10276     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10277     newsubcomm = PETSC_TRUE;
10278     PetscCall(PetscSubcommDestroy(&psubcomm));
10279   }
10280 
10281   /* get isrow, iscol and a local sequential matrix matseq[0] */
10282   if (reuse == MAT_INITIAL_MATRIX) {
10283     mloc_sub = PETSC_DECIDE;
10284     nloc_sub = PETSC_DECIDE;
10285     if (bs < 1) {
10286       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10287       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10288     } else {
10289       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10290       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10291     }
10292     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10293     rstart = rend - mloc_sub;
10294     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10295     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10296   } else { /* reuse == MAT_REUSE_MATRIX */
10297     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");
10298     /* retrieve subcomm */
10299     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10300     redund = (*matredundant)->redundant;
10301     isrow  = redund->isrow;
10302     iscol  = redund->iscol;
10303     matseq = redund->matseq;
10304   }
10305   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10306 
10307   /* get matredundant over subcomm */
10308   if (reuse == MAT_INITIAL_MATRIX) {
10309     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10310 
10311     /* create a supporting struct and attach it to C for reuse */
10312     PetscCall(PetscNew(&redund));
10313     (*matredundant)->redundant = redund;
10314     redund->isrow              = isrow;
10315     redund->iscol              = iscol;
10316     redund->matseq             = matseq;
10317     if (newsubcomm) {
10318       redund->subcomm = subcomm;
10319     } else {
10320       redund->subcomm = MPI_COMM_NULL;
10321     }
10322   } else {
10323     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10324   }
10325 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10326   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10327     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10328     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10329   }
10330 #endif
10331   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10332   PetscFunctionReturn(PETSC_SUCCESS);
10333 }
10334 
10335 /*@C
10336    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10337    a given `Mat`. Each submatrix can span multiple procs.
10338 
10339    Collective
10340 
10341    Input Parameters:
10342 +  mat - the matrix
10343 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10344 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10345 
10346    Output Parameter:
10347 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10348 
10349   Level: advanced
10350 
10351   Notes:
10352   The submatrix partition across processors is dictated by `subComm` a
10353   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10354   is not restricted to be grouped with consecutive original ranks.
10355 
10356   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10357   map directly to the layout of the original matrix [wrt the local
10358   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10359   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10360   the `subMat`. However the offDiagMat looses some columns - and this is
10361   reconstructed with `MatSetValues()`
10362 
10363   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10364 
10365 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10366 @*/
10367 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10368 {
10369   PetscMPIInt commsize, subCommSize;
10370 
10371   PetscFunctionBegin;
10372   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10373   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10374   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10375 
10376   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");
10377   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10378   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10379   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10380   PetscFunctionReturn(PETSC_SUCCESS);
10381 }
10382 
10383 /*@
10384    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10385 
10386    Not Collective
10387 
10388    Input Parameters:
10389 +  mat - matrix to extract local submatrix from
10390 .  isrow - local row indices for submatrix
10391 -  iscol - local column indices for submatrix
10392 
10393    Output Parameter:
10394 .  submat - the submatrix
10395 
10396    Level: intermediate
10397 
10398    Notes:
10399    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10400 
10401    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10402    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10403 
10404    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10405    `MatSetValuesBlockedLocal()` will also be implemented.
10406 
10407    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10408    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10409 
10410 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10411 @*/
10412 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10413 {
10414   PetscFunctionBegin;
10415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10416   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10417   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10418   PetscCheckSameComm(isrow, 2, iscol, 3);
10419   PetscValidPointer(submat, 4);
10420   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10421 
10422   if (mat->ops->getlocalsubmatrix) {
10423     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10424   } else {
10425     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10426   }
10427   PetscFunctionReturn(PETSC_SUCCESS);
10428 }
10429 
10430 /*@
10431    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10432 
10433    Not Collective
10434 
10435    Input Parameters:
10436 +  mat - matrix to extract local submatrix from
10437 .  isrow - local row indices for submatrix
10438 .  iscol - local column indices for submatrix
10439 -  submat - the submatrix
10440 
10441    Level: intermediate
10442 
10443 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10444 @*/
10445 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10446 {
10447   PetscFunctionBegin;
10448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10449   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10450   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10451   PetscCheckSameComm(isrow, 2, iscol, 3);
10452   PetscValidPointer(submat, 4);
10453   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10454 
10455   if (mat->ops->restorelocalsubmatrix) {
10456     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10457   } else {
10458     PetscCall(MatDestroy(submat));
10459   }
10460   *submat = NULL;
10461   PetscFunctionReturn(PETSC_SUCCESS);
10462 }
10463 
10464 /*@
10465    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10466 
10467    Collective
10468 
10469    Input Parameter:
10470 .  mat - the matrix
10471 
10472    Output Parameter:
10473 .  is - if any rows have zero diagonals this contains the list of them
10474 
10475    Level: developer
10476 
10477 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10478 @*/
10479 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10480 {
10481   PetscFunctionBegin;
10482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10483   PetscValidType(mat, 1);
10484   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10485   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10486 
10487   if (!mat->ops->findzerodiagonals) {
10488     Vec                diag;
10489     const PetscScalar *a;
10490     PetscInt          *rows;
10491     PetscInt           rStart, rEnd, r, nrow = 0;
10492 
10493     PetscCall(MatCreateVecs(mat, &diag, NULL));
10494     PetscCall(MatGetDiagonal(mat, diag));
10495     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10496     PetscCall(VecGetArrayRead(diag, &a));
10497     for (r = 0; r < rEnd - rStart; ++r)
10498       if (a[r] == 0.0) ++nrow;
10499     PetscCall(PetscMalloc1(nrow, &rows));
10500     nrow = 0;
10501     for (r = 0; r < rEnd - rStart; ++r)
10502       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10503     PetscCall(VecRestoreArrayRead(diag, &a));
10504     PetscCall(VecDestroy(&diag));
10505     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10506   } else {
10507     PetscUseTypeMethod(mat, findzerodiagonals, is);
10508   }
10509   PetscFunctionReturn(PETSC_SUCCESS);
10510 }
10511 
10512 /*@
10513    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10514 
10515    Collective
10516 
10517    Input Parameter:
10518 .  mat - the matrix
10519 
10520    Output Parameter:
10521 .  is - contains the list of rows with off block diagonal entries
10522 
10523    Level: developer
10524 
10525 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10526 @*/
10527 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10528 {
10529   PetscFunctionBegin;
10530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10531   PetscValidType(mat, 1);
10532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10533   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10534 
10535   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10536   PetscFunctionReturn(PETSC_SUCCESS);
10537 }
10538 
10539 /*@C
10540   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10541 
10542   Collective; No Fortran Support
10543 
10544   Input Parameter:
10545 . mat - the matrix
10546 
10547   Output Parameter:
10548 . values - the block inverses in column major order (FORTRAN-like)
10549 
10550   Level: advanced
10551 
10552    Notes:
10553    The size of the blocks is determined by the block size of the matrix.
10554 
10555    The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10556 
10557    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10558 
10559 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10560 @*/
10561 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10562 {
10563   PetscFunctionBegin;
10564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10567   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10568   PetscFunctionReturn(PETSC_SUCCESS);
10569 }
10570 
10571 /*@C
10572   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10573 
10574   Collective; No Fortran Support
10575 
10576   Input Parameters:
10577 + mat - the matrix
10578 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10579 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10580 
10581   Output Parameter:
10582 . values - the block inverses in column major order (FORTRAN-like)
10583 
10584   Level: advanced
10585 
10586   Notes:
10587   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10588 
10589   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10590 
10591 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10592 @*/
10593 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10594 {
10595   PetscFunctionBegin;
10596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10597   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10598   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10599   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10600   PetscFunctionReturn(PETSC_SUCCESS);
10601 }
10602 
10603 /*@
10604   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10605 
10606   Collective
10607 
10608   Input Parameters:
10609 + A - the matrix
10610 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10611 
10612   Level: advanced
10613 
10614   Note:
10615   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10616 
10617 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10618 @*/
10619 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10620 {
10621   const PetscScalar *vals;
10622   PetscInt          *dnnz;
10623   PetscInt           m, rstart, rend, bs, i, j;
10624 
10625   PetscFunctionBegin;
10626   PetscCall(MatInvertBlockDiagonal(A, &vals));
10627   PetscCall(MatGetBlockSize(A, &bs));
10628   PetscCall(MatGetLocalSize(A, &m, NULL));
10629   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10630   PetscCall(PetscMalloc1(m / bs, &dnnz));
10631   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10632   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10633   PetscCall(PetscFree(dnnz));
10634   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10635   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10636   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10637   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10638   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10639   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10640   PetscFunctionReturn(PETSC_SUCCESS);
10641 }
10642 
10643 /*@C
10644     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10645     via `MatTransposeColoringCreate()`.
10646 
10647     Collective
10648 
10649     Input Parameter:
10650 .   c - coloring context
10651 
10652     Level: intermediate
10653 
10654 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10655 @*/
10656 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10657 {
10658   MatTransposeColoring matcolor = *c;
10659 
10660   PetscFunctionBegin;
10661   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10662   if (--((PetscObject)matcolor)->refct > 0) {
10663     matcolor = NULL;
10664     PetscFunctionReturn(PETSC_SUCCESS);
10665   }
10666 
10667   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10668   PetscCall(PetscFree(matcolor->rows));
10669   PetscCall(PetscFree(matcolor->den2sp));
10670   PetscCall(PetscFree(matcolor->colorforcol));
10671   PetscCall(PetscFree(matcolor->columns));
10672   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10673   PetscCall(PetscHeaderDestroy(c));
10674   PetscFunctionReturn(PETSC_SUCCESS);
10675 }
10676 
10677 /*@C
10678     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10679     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10680     `MatTransposeColoring` to sparse B.
10681 
10682     Collective
10683 
10684     Input Parameters:
10685 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10686 -   B - sparse matrix
10687 
10688     Output Parameter:
10689 .   Btdense - dense matrix B^T
10690 
10691     Level: developer
10692 
10693     Note:
10694     These are used internally for some implementations of `MatRARt()`
10695 
10696 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10697 @*/
10698 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10699 {
10700   PetscFunctionBegin;
10701   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10702   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10703   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10704 
10705   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10706   PetscFunctionReturn(PETSC_SUCCESS);
10707 }
10708 
10709 /*@C
10710     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10711     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10712     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10713     `Csp` from `Cden`.
10714 
10715     Collective
10716 
10717     Input Parameters:
10718 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10719 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10720 
10721     Output Parameter:
10722 .   Csp - sparse matrix
10723 
10724     Level: developer
10725 
10726     Note:
10727     These are used internally for some implementations of `MatRARt()`
10728 
10729 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10730 @*/
10731 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10732 {
10733   PetscFunctionBegin;
10734   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10735   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10736   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10737 
10738   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10739   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10740   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10741   PetscFunctionReturn(PETSC_SUCCESS);
10742 }
10743 
10744 /*@C
10745    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10746 
10747    Collective
10748 
10749    Input Parameters:
10750 +  mat - the matrix product C
10751 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10752 
10753     Output Parameter:
10754 .   color - the new coloring context
10755 
10756     Level: intermediate
10757 
10758 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10759           `MatTransColoringApplyDenToSp()`
10760 @*/
10761 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10762 {
10763   MatTransposeColoring c;
10764   MPI_Comm             comm;
10765 
10766   PetscFunctionBegin;
10767   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10768   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10769   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10770 
10771   c->ctype = iscoloring->ctype;
10772   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10773 
10774   *color = c;
10775   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10776   PetscFunctionReturn(PETSC_SUCCESS);
10777 }
10778 
10779 /*@
10780       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10781         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10782         same, otherwise it will be larger
10783 
10784      Not Collective
10785 
10786   Input Parameter:
10787 .    A  - the matrix
10788 
10789   Output Parameter:
10790 .    state - the current state
10791 
10792   Level: intermediate
10793 
10794   Notes:
10795     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10796          different matrices
10797 
10798     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10799 
10800     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10801 
10802 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10803 @*/
10804 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10805 {
10806   PetscFunctionBegin;
10807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10808   *state = mat->nonzerostate;
10809   PetscFunctionReturn(PETSC_SUCCESS);
10810 }
10811 
10812 /*@
10813       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10814                  matrices from each processor
10815 
10816     Collective
10817 
10818    Input Parameters:
10819 +    comm - the communicators the parallel matrix will live on
10820 .    seqmat - the input sequential matrices
10821 .    n - number of local columns (or `PETSC_DECIDE`)
10822 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10823 
10824    Output Parameter:
10825 .    mpimat - the parallel matrix generated
10826 
10827     Level: developer
10828 
10829    Note:
10830     The number of columns of the matrix in EACH processor MUST be the same.
10831 
10832 .seealso: [](ch_matrices), `Mat`
10833 @*/
10834 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10835 {
10836   PetscMPIInt size;
10837 
10838   PetscFunctionBegin;
10839   PetscCallMPI(MPI_Comm_size(comm, &size));
10840   if (size == 1) {
10841     if (reuse == MAT_INITIAL_MATRIX) {
10842       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10843     } else {
10844       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10845     }
10846     PetscFunctionReturn(PETSC_SUCCESS);
10847   }
10848 
10849   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");
10850 
10851   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10852   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10853   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10854   PetscFunctionReturn(PETSC_SUCCESS);
10855 }
10856 
10857 /*@
10858      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10859 
10860     Collective
10861 
10862    Input Parameters:
10863 +    A   - the matrix to create subdomains from
10864 -    N   - requested number of subdomains
10865 
10866    Output Parameters:
10867 +    n   - number of subdomains resulting on this MPI process
10868 -    iss - `IS` list with indices of subdomains on this MPI process
10869 
10870     Level: advanced
10871 
10872     Note:
10873     The number of subdomains must be smaller than the communicator size
10874 
10875 .seealso: [](ch_matrices), `Mat`, `IS`
10876 @*/
10877 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10878 {
10879   MPI_Comm    comm, subcomm;
10880   PetscMPIInt size, rank, color;
10881   PetscInt    rstart, rend, k;
10882 
10883   PetscFunctionBegin;
10884   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10885   PetscCallMPI(MPI_Comm_size(comm, &size));
10886   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10887   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);
10888   *n    = 1;
10889   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10890   color = rank / k;
10891   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10892   PetscCall(PetscMalloc1(1, iss));
10893   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10894   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10895   PetscCallMPI(MPI_Comm_free(&subcomm));
10896   PetscFunctionReturn(PETSC_SUCCESS);
10897 }
10898 
10899 /*@
10900    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10901 
10902    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10903    If they are not the same, uses `MatMatMatMult()`.
10904 
10905    Once the coarse grid problem is constructed, correct for interpolation operators
10906    that are not of full rank, which can legitimately happen in the case of non-nested
10907    geometric multigrid.
10908 
10909    Input Parameters:
10910 +  restrct - restriction operator
10911 .  dA - fine grid matrix
10912 .  interpolate - interpolation operator
10913 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10914 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10915 
10916    Output Parameter:
10917 .  A - the Galerkin coarse matrix
10918 
10919    Options Database Key:
10920 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10921 
10922    Level: developer
10923 
10924 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10925 @*/
10926 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10927 {
10928   IS  zerorows;
10929   Vec diag;
10930 
10931   PetscFunctionBegin;
10932   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10933   /* Construct the coarse grid matrix */
10934   if (interpolate == restrct) {
10935     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10936   } else {
10937     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10938   }
10939 
10940   /* If the interpolation matrix is not of full rank, A will have zero rows.
10941      This can legitimately happen in the case of non-nested geometric multigrid.
10942      In that event, we set the rows of the matrix to the rows of the identity,
10943      ignoring the equations (as the RHS will also be zero). */
10944 
10945   PetscCall(MatFindZeroRows(*A, &zerorows));
10946 
10947   if (zerorows != NULL) { /* if there are any zero rows */
10948     PetscCall(MatCreateVecs(*A, &diag, NULL));
10949     PetscCall(MatGetDiagonal(*A, diag));
10950     PetscCall(VecISSet(diag, zerorows, 1.0));
10951     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10952     PetscCall(VecDestroy(&diag));
10953     PetscCall(ISDestroy(&zerorows));
10954   }
10955   PetscFunctionReturn(PETSC_SUCCESS);
10956 }
10957 
10958 /*@C
10959     MatSetOperation - Allows user to set a matrix operation for any matrix type
10960 
10961    Logically Collective
10962 
10963     Input Parameters:
10964 +   mat - the matrix
10965 .   op - the name of the operation
10966 -   f - the function that provides the operation
10967 
10968    Level: developer
10969 
10970     Usage:
10971 .vb
10972   extern PetscErrorCode usermult(Mat, Vec, Vec);
10973 
10974   PetscCall(MatCreateXXX(comm, ..., &A));
10975   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10976 .ve
10977 
10978     Notes:
10979     See the file `include/petscmat.h` for a complete list of matrix
10980     operations, which all have the form MATOP_<OPERATION>, where
10981     <OPERATION> is the name (in all capital letters) of the
10982     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10983 
10984     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10985     sequence as the usual matrix interface routines, since they
10986     are intended to be accessed via the usual matrix interface
10987     routines, e.g.,
10988 .vb
10989   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10990 .ve
10991 
10992     In particular each function MUST return `PETSC_SUCCESS` on success and
10993     nonzero on failure.
10994 
10995     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10996 
10997 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10998 @*/
10999 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11000 {
11001   PetscFunctionBegin;
11002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11003   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11004   (((void (**)(void))mat->ops)[op]) = f;
11005   PetscFunctionReturn(PETSC_SUCCESS);
11006 }
11007 
11008 /*@C
11009     MatGetOperation - Gets a matrix operation for any matrix type.
11010 
11011     Not Collective
11012 
11013     Input Parameters:
11014 +   mat - the matrix
11015 -   op - the name of the operation
11016 
11017     Output Parameter:
11018 .   f - the function that provides the operation
11019 
11020     Level: developer
11021 
11022     Usage:
11023 .vb
11024       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11025       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11026 .ve
11027 
11028     Notes:
11029     See the file include/petscmat.h for a complete list of matrix
11030     operations, which all have the form MATOP_<OPERATION>, where
11031     <OPERATION> is the name (in all capital letters) of the
11032     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11033 
11034     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11035 
11036 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11037 @*/
11038 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11039 {
11040   PetscFunctionBegin;
11041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11042   *f = (((void (**)(void))mat->ops)[op]);
11043   PetscFunctionReturn(PETSC_SUCCESS);
11044 }
11045 
11046 /*@
11047     MatHasOperation - Determines whether the given matrix supports the particular operation.
11048 
11049    Not Collective
11050 
11051    Input Parameters:
11052 +  mat - the matrix
11053 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11054 
11055    Output Parameter:
11056 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11057 
11058    Level: advanced
11059 
11060    Note:
11061    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11062 
11063 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11064 @*/
11065 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11066 {
11067   PetscFunctionBegin;
11068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11069   PetscValidBoolPointer(has, 3);
11070   if (mat->ops->hasoperation) {
11071     PetscUseTypeMethod(mat, hasoperation, op, has);
11072   } else {
11073     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11074     else {
11075       *has = PETSC_FALSE;
11076       if (op == MATOP_CREATE_SUBMATRIX) {
11077         PetscMPIInt size;
11078 
11079         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11080         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11081       }
11082     }
11083   }
11084   PetscFunctionReturn(PETSC_SUCCESS);
11085 }
11086 
11087 /*@
11088     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11089 
11090    Collective
11091 
11092    Input Parameter:
11093 .  mat - the matrix
11094 
11095    Output Parameter:
11096 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11097 
11098    Level: beginner
11099 
11100 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11101 @*/
11102 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11103 {
11104   PetscFunctionBegin;
11105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11106   PetscValidType(mat, 1);
11107   PetscValidBoolPointer(cong, 2);
11108   if (!mat->rmap || !mat->cmap) {
11109     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11110     PetscFunctionReturn(PETSC_SUCCESS);
11111   }
11112   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11113     PetscCall(PetscLayoutSetUp(mat->rmap));
11114     PetscCall(PetscLayoutSetUp(mat->cmap));
11115     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11116     if (*cong) mat->congruentlayouts = 1;
11117     else mat->congruentlayouts = 0;
11118   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11119   PetscFunctionReturn(PETSC_SUCCESS);
11120 }
11121 
11122 PetscErrorCode MatSetInf(Mat A)
11123 {
11124   PetscFunctionBegin;
11125   PetscUseTypeMethod(A, setinf);
11126   PetscFunctionReturn(PETSC_SUCCESS);
11127 }
11128 
11129 /*@C
11130    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
11131    and possibly removes small values from the graph structure.
11132 
11133    Collective
11134 
11135    Input Parameters:
11136 +  A - the matrix
11137 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11138 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11139 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11140 
11141    Output Parameter:
11142 .  graph - the resulting graph
11143 
11144    Level: advanced
11145 
11146 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11147 @*/
11148 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11149 {
11150   PetscFunctionBegin;
11151   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11152   PetscValidType(A, 1);
11153   PetscValidLogicalCollectiveBool(A, scale, 3);
11154   PetscValidPointer(graph, 5);
11155   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11156   PetscFunctionReturn(PETSC_SUCCESS);
11157 }
11158 
11159 /*@
11160   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11161   meaning the same memory is used for the matrix, and no new memory is allocated.
11162 
11163   Collective
11164 
11165   Input Parameter:
11166 . A - the matrix
11167 
11168   Level: intermediate
11169 
11170   Developer Note:
11171   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11172   of the arrays in the data structure are unneeded.
11173 
11174 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11175 @*/
11176 PetscErrorCode MatEliminateZeros(Mat A)
11177 {
11178   PetscFunctionBegin;
11179   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11180   PetscUseTypeMethod(A, eliminatezeros);
11181   PetscFunctionReturn(PETSC_SUCCESS);
11182 }
11183