xref: /petsc/src/mat/interface/matrix.c (revision 422617d9fdc200ea07698d13a116ecdb293b8b3b)
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 multiplied
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   PetscValidType(fact, 1);
3233   PetscValidType(mat, 2);
3234   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3235   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,
3236              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3237 
3238   MatCheckPreallocated(mat, 2);
3239   if (!info) {
3240     PetscCall(MatFactorInfoInitialize(&tinfo));
3241     info = &tinfo;
3242   }
3243 
3244   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3245   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3246   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3247   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3248   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3249   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3250   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3251   PetscFunctionReturn(PETSC_SUCCESS);
3252 }
3253 
3254 /*@C
3255    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3256    symmetric matrix.
3257 
3258    Collective
3259 
3260    Input Parameters:
3261 +  mat - the matrix
3262 .  perm - row and column permutations
3263 -  f - expected fill as ratio of original fill
3264 
3265    Level: developer
3266 
3267    Notes:
3268    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3269    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3270 
3271    Most users should employ the `KSP` interface for linear solvers
3272    instead of working directly with matrix algebra routines such as this.
3273    See, e.g., `KSPCreate()`.
3274 
3275    Developer Note:
3276    The Fortran interface is not autogenerated as the
3277    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3278 
3279 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3280           `MatGetOrdering()`
3281 @*/
3282 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3283 {
3284   MatFactorInfo tinfo;
3285 
3286   PetscFunctionBegin;
3287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3288   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3289   if (info) PetscValidPointer(info, 3);
3290   PetscValidType(mat, 1);
3291   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3294   MatCheckPreallocated(mat, 1);
3295   if (!info) {
3296     PetscCall(MatFactorInfoInitialize(&tinfo));
3297     info = &tinfo;
3298   }
3299 
3300   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3301   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3302   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3303   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3304   PetscFunctionReturn(PETSC_SUCCESS);
3305 }
3306 
3307 /*@C
3308    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3309    of a symmetric matrix.
3310 
3311    Collective
3312 
3313    Input Parameters:
3314 +  fact - the factor matrix obtained with `MatGetFactor()`
3315 .  mat - the matrix
3316 .  perm - row and column permutations
3317 -  info - options for factorization, includes
3318 .vb
3319           fill - expected fill as ratio of original fill.
3320           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3321                    Run with the option -info to determine an optimal value to use
3322 .ve
3323 
3324    Level: developer
3325 
3326    Notes:
3327    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3328    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3329 
3330    Most users should employ the `KSP` interface for linear solvers
3331    instead of working directly with matrix algebra routines such as this.
3332    See, e.g., `KSPCreate()`.
3333 
3334    Developer Note:
3335    The Fortran interface is not autogenerated as the
3336    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3337 
3338 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3339           `MatGetOrdering()`
3340 @*/
3341 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3342 {
3343   MatFactorInfo tinfo;
3344 
3345   PetscFunctionBegin;
3346   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3348   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3349   if (info) PetscValidPointer(info, 4);
3350   PetscValidType(fact, 1);
3351   PetscValidType(mat, 2);
3352   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3353   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3354   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3355   MatCheckPreallocated(mat, 2);
3356   if (!info) {
3357     PetscCall(MatFactorInfoInitialize(&tinfo));
3358     info = &tinfo;
3359   }
3360 
3361   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3362   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3363   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3364   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3365   PetscFunctionReturn(PETSC_SUCCESS);
3366 }
3367 
3368 /*@C
3369    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3370    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3371    `MatCholeskyFactorSymbolic()`.
3372 
3373    Collective
3374 
3375    Input Parameters:
3376 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3377 .  mat - the initial matrix that is to be factored
3378 -  info - options for factorization
3379 
3380    Level: developer
3381 
3382    Note:
3383    Most users should employ the `KSP` interface for linear solvers
3384    instead of working directly with matrix algebra routines such as this.
3385    See, e.g., `KSPCreate()`.
3386 
3387    Developer Note:
3388    The Fortran interface is not autogenerated as the
3389    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3390 
3391 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3392 @*/
3393 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3394 {
3395   MatFactorInfo tinfo;
3396 
3397   PetscFunctionBegin;
3398   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3400   PetscValidType(fact, 1);
3401   PetscValidType(mat, 2);
3402   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3403   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,
3404              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3405   MatCheckPreallocated(mat, 2);
3406   if (!info) {
3407     PetscCall(MatFactorInfoInitialize(&tinfo));
3408     info = &tinfo;
3409   }
3410 
3411   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3412   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3413   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3414   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3415   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3416   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3417   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3418   PetscFunctionReturn(PETSC_SUCCESS);
3419 }
3420 
3421 /*@
3422    MatQRFactor - Performs in-place QR factorization of matrix.
3423 
3424    Collective
3425 
3426    Input Parameters:
3427 +  mat - the matrix
3428 .  col - column permutation
3429 -  info - options for factorization, includes
3430 .vb
3431           fill - expected fill as ratio of original fill.
3432           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3433                    Run with the option -info to determine an optimal value to use
3434 .ve
3435 
3436    Level: developer
3437 
3438    Notes:
3439    Most users should employ the `KSP` interface for linear solvers
3440    instead of working directly with matrix algebra routines such as this.
3441    See, e.g., `KSPCreate()`.
3442 
3443    This changes the state of the matrix to a factored matrix; it cannot be used
3444    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3445 
3446    Developer Note:
3447    The Fortran interface is not autogenerated as the
3448    interface definition cannot be generated correctly [due to MatFactorInfo]
3449 
3450 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3451           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3452 @*/
3453 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3454 {
3455   PetscFunctionBegin;
3456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3457   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3458   if (info) PetscValidPointer(info, 3);
3459   PetscValidType(mat, 1);
3460   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3461   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3462   MatCheckPreallocated(mat, 1);
3463   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3464   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3465   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3466   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3467   PetscFunctionReturn(PETSC_SUCCESS);
3468 }
3469 
3470 /*@
3471    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3472    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3473 
3474    Collective
3475 
3476    Input Parameters:
3477 +  fact - the factor matrix obtained with `MatGetFactor()`
3478 .  mat - the matrix
3479 .  col - column permutation
3480 -  info - options for factorization, includes
3481 .vb
3482           fill - expected fill as ratio of original fill.
3483           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3484                    Run with the option -info to determine an optimal value to use
3485 .ve
3486 
3487    Level: developer
3488 
3489    Note:
3490    Most users should employ the `KSP` interface for linear solvers
3491    instead of working directly with matrix algebra routines such as this.
3492    See, e.g., `KSPCreate()`.
3493 
3494    Developer Note:
3495    The Fortran interface is not autogenerated as the
3496    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3497 
3498 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3499 @*/
3500 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3501 {
3502   MatFactorInfo tinfo;
3503 
3504   PetscFunctionBegin;
3505   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3506   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3507   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3508   if (info) PetscValidPointer(info, 4);
3509   PetscValidType(fact, 1);
3510   PetscValidType(mat, 2);
3511   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3512   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3513   MatCheckPreallocated(mat, 2);
3514   if (!info) {
3515     PetscCall(MatFactorInfoInitialize(&tinfo));
3516     info = &tinfo;
3517   }
3518 
3519   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3520   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3521   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3522   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3523   PetscFunctionReturn(PETSC_SUCCESS);
3524 }
3525 
3526 /*@
3527    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3528    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3529 
3530    Collective
3531 
3532    Input Parameters:
3533 +  fact - the factor matrix obtained with `MatGetFactor()`
3534 .  mat - the matrix
3535 -  info - options for factorization
3536 
3537    Level: developer
3538 
3539    Notes:
3540    See `MatQRFactor()` for in-place factorization.
3541 
3542    Most users should employ the `KSP` interface for linear solvers
3543    instead of working directly with matrix algebra routines such as this.
3544    See, e.g., `KSPCreate()`.
3545 
3546    Developer Note:
3547    The Fortran interface is not autogenerated as the
3548    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3549 
3550 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3551 @*/
3552 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3553 {
3554   MatFactorInfo tinfo;
3555 
3556   PetscFunctionBegin;
3557   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3559   PetscValidType(fact, 1);
3560   PetscValidType(mat, 2);
3561   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3562   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,
3563              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3564 
3565   MatCheckPreallocated(mat, 2);
3566   if (!info) {
3567     PetscCall(MatFactorInfoInitialize(&tinfo));
3568     info = &tinfo;
3569   }
3570 
3571   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3572   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3573   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3574   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3575   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3576   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3577   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3578   PetscFunctionReturn(PETSC_SUCCESS);
3579 }
3580 
3581 /*@
3582    MatSolve - Solves A x = b, given a factored matrix.
3583 
3584    Neighbor-wise Collective
3585 
3586    Input Parameters:
3587 +  mat - the factored matrix
3588 -  b - the right-hand-side vector
3589 
3590    Output Parameter:
3591 .  x - the result vector
3592 
3593    Level: developer
3594 
3595    Notes:
3596    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3597    call `MatSolve`(A,x,x).
3598 
3599    Most users should employ the `KSP` interface for linear solvers
3600    instead of working directly with matrix algebra routines such as this.
3601    See, e.g., `KSPCreate()`.
3602 
3603 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3604 @*/
3605 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3606 {
3607   PetscFunctionBegin;
3608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3609   PetscValidType(mat, 1);
3610   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3611   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3612   PetscCheckSameComm(mat, 1, b, 2);
3613   PetscCheckSameComm(mat, 1, x, 3);
3614   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3615   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);
3616   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);
3617   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);
3618   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3619   MatCheckPreallocated(mat, 1);
3620 
3621   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3622   if (mat->factorerrortype) {
3623     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3624     PetscCall(VecSetInf(x));
3625   } else PetscUseTypeMethod(mat, solve, b, x);
3626   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3627   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3628   PetscFunctionReturn(PETSC_SUCCESS);
3629 }
3630 
3631 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3632 {
3633   Vec      b, x;
3634   PetscInt N, i;
3635   PetscErrorCode (*f)(Mat, Vec, Vec);
3636   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3637 
3638   PetscFunctionBegin;
3639   if (A->factorerrortype) {
3640     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3641     PetscCall(MatSetInf(X));
3642     PetscFunctionReturn(PETSC_SUCCESS);
3643   }
3644   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3645   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3646   PetscCall(MatBoundToCPU(A, &Abound));
3647   if (!Abound) {
3648     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3649     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3650   }
3651 #if PetscDefined(HAVE_CUDA)
3652   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3653   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3654 #elif PetscDefined(HAVE_HIP)
3655   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3656   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3657 #endif
3658   PetscCall(MatGetSize(B, NULL, &N));
3659   for (i = 0; i < N; i++) {
3660     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3661     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3662     PetscCall((*f)(A, b, x));
3663     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3664     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3665   }
3666   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3667   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3668   PetscFunctionReturn(PETSC_SUCCESS);
3669 }
3670 
3671 /*@
3672    MatMatSolve - Solves A X = B, given a factored matrix.
3673 
3674    Neighbor-wise Collective
3675 
3676    Input Parameters:
3677 +  A - the factored matrix
3678 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3679 
3680    Output Parameter:
3681 .  X - the result matrix (dense matrix)
3682 
3683    Level: developer
3684 
3685    Note:
3686    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3687    otherwise, `B` and `X` cannot be the same.
3688 
3689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3690 @*/
3691 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3692 {
3693   PetscFunctionBegin;
3694   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3695   PetscValidType(A, 1);
3696   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3697   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3698   PetscCheckSameComm(A, 1, B, 2);
3699   PetscCheckSameComm(A, 1, X, 3);
3700   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);
3701   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);
3702   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");
3703   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3704   MatCheckPreallocated(A, 1);
3705 
3706   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3707   if (!A->ops->matsolve) {
3708     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3709     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3710   } else PetscUseTypeMethod(A, matsolve, B, X);
3711   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3712   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3713   PetscFunctionReturn(PETSC_SUCCESS);
3714 }
3715 
3716 /*@
3717    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3718 
3719    Neighbor-wise Collective
3720 
3721    Input Parameters:
3722 +  A - the factored matrix
3723 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3724 
3725    Output Parameter:
3726 .  X - the result matrix (dense matrix)
3727 
3728    Level: developer
3729 
3730    Note:
3731    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3732    call `MatMatSolveTranspose`(A,X,X).
3733 
3734 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3735 @*/
3736 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3737 {
3738   PetscFunctionBegin;
3739   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3740   PetscValidType(A, 1);
3741   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3742   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3743   PetscCheckSameComm(A, 1, B, 2);
3744   PetscCheckSameComm(A, 1, X, 3);
3745   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3746   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);
3747   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);
3748   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);
3749   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");
3750   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3751   MatCheckPreallocated(A, 1);
3752 
3753   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3754   if (!A->ops->matsolvetranspose) {
3755     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3756     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3757   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3758   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3759   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3760   PetscFunctionReturn(PETSC_SUCCESS);
3761 }
3762 
3763 /*@
3764    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3765 
3766    Neighbor-wise Collective
3767 
3768    Input Parameters:
3769 +  A - the factored matrix
3770 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3771 
3772    Output Parameter:
3773 .  X - the result matrix (dense matrix)
3774 
3775    Level: developer
3776 
3777    Note:
3778    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
3779    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3780 
3781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3782 @*/
3783 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3784 {
3785   PetscFunctionBegin;
3786   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3787   PetscValidType(A, 1);
3788   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3789   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3790   PetscCheckSameComm(A, 1, Bt, 2);
3791   PetscCheckSameComm(A, 1, X, 3);
3792 
3793   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3794   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);
3795   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);
3796   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");
3797   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3798   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3799   MatCheckPreallocated(A, 1);
3800 
3801   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3802   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3803   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3804   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3805   PetscFunctionReturn(PETSC_SUCCESS);
3806 }
3807 
3808 /*@
3809    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3810                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3811 
3812    Neighbor-wise Collective
3813 
3814    Input Parameters:
3815 +  mat - the factored matrix
3816 -  b - the right-hand-side vector
3817 
3818    Output Parameter:
3819 .  x - the result vector
3820 
3821    Level: developer
3822 
3823    Notes:
3824    `MatSolve()` should be used for most applications, as it performs
3825    a forward solve followed by a backward solve.
3826 
3827    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3828    call `MatForwardSolve`(A,x,x).
3829 
3830    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3831    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3832    `MatForwardSolve()` solves U^T*D y = b, and
3833    `MatBackwardSolve()` solves U x = y.
3834    Thus they do not provide a symmetric preconditioner.
3835 
3836 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3837 @*/
3838 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3839 {
3840   PetscFunctionBegin;
3841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3842   PetscValidType(mat, 1);
3843   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3844   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3845   PetscCheckSameComm(mat, 1, b, 2);
3846   PetscCheckSameComm(mat, 1, x, 3);
3847   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3848   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);
3849   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);
3850   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);
3851   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3852   MatCheckPreallocated(mat, 1);
3853 
3854   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3855   PetscUseTypeMethod(mat, forwardsolve, b, x);
3856   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3857   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3858   PetscFunctionReturn(PETSC_SUCCESS);
3859 }
3860 
3861 /*@
3862    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3863                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3864 
3865    Neighbor-wise Collective
3866 
3867    Input Parameters:
3868 +  mat - the factored matrix
3869 -  b - the right-hand-side vector
3870 
3871    Output Parameter:
3872 .  x - the result vector
3873 
3874    Level: developer
3875 
3876    Notes:
3877    `MatSolve()` should be used for most applications, as it performs
3878    a forward solve followed by a backward solve.
3879 
3880    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3881    call `MatBackwardSolve`(A,x,x).
3882 
3883    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3884    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3885    `MatForwardSolve()` solves U^T*D y = b, and
3886    `MatBackwardSolve()` solves U x = y.
3887    Thus they do not provide a symmetric preconditioner.
3888 
3889 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3890 @*/
3891 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3892 {
3893   PetscFunctionBegin;
3894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3895   PetscValidType(mat, 1);
3896   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3897   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3898   PetscCheckSameComm(mat, 1, b, 2);
3899   PetscCheckSameComm(mat, 1, x, 3);
3900   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3901   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);
3902   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);
3903   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);
3904   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3905   MatCheckPreallocated(mat, 1);
3906 
3907   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3908   PetscUseTypeMethod(mat, backwardsolve, b, x);
3909   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3910   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3911   PetscFunctionReturn(PETSC_SUCCESS);
3912 }
3913 
3914 /*@
3915    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3916 
3917    Neighbor-wise Collective
3918 
3919    Input Parameters:
3920 +  mat - the factored matrix
3921 .  b - the right-hand-side vector
3922 -  y - the vector to be added to
3923 
3924    Output Parameter:
3925 .  x - the result vector
3926 
3927    Level: developer
3928 
3929    Note:
3930    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3931    call `MatSolveAdd`(A,x,y,x).
3932 
3933 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3934 @*/
3935 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3936 {
3937   PetscScalar one = 1.0;
3938   Vec         tmp;
3939 
3940   PetscFunctionBegin;
3941   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3942   PetscValidType(mat, 1);
3943   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3944   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3945   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3946   PetscCheckSameComm(mat, 1, b, 2);
3947   PetscCheckSameComm(mat, 1, y, 3);
3948   PetscCheckSameComm(mat, 1, x, 4);
3949   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3950   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);
3951   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);
3952   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);
3953   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);
3954   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);
3955   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3956   MatCheckPreallocated(mat, 1);
3957 
3958   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3959   if (mat->factorerrortype) {
3960     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3961     PetscCall(VecSetInf(x));
3962   } else if (mat->ops->solveadd) {
3963     PetscUseTypeMethod(mat, solveadd, b, y, x);
3964   } else {
3965     /* do the solve then the add manually */
3966     if (x != y) {
3967       PetscCall(MatSolve(mat, b, x));
3968       PetscCall(VecAXPY(x, one, y));
3969     } else {
3970       PetscCall(VecDuplicate(x, &tmp));
3971       PetscCall(VecCopy(x, tmp));
3972       PetscCall(MatSolve(mat, b, x));
3973       PetscCall(VecAXPY(x, one, tmp));
3974       PetscCall(VecDestroy(&tmp));
3975     }
3976   }
3977   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3978   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3979   PetscFunctionReturn(PETSC_SUCCESS);
3980 }
3981 
3982 /*@
3983    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3984 
3985    Neighbor-wise Collective
3986 
3987    Input Parameters:
3988 +  mat - the factored matrix
3989 -  b - the right-hand-side vector
3990 
3991    Output Parameter:
3992 .  x - the result vector
3993 
3994    Level: developer
3995 
3996    Notes:
3997    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3998    call `MatSolveTranspose`(A,x,x).
3999 
4000    Most users should employ the `KSP` interface for linear solvers
4001    instead of working directly with matrix algebra routines such as this.
4002    See, e.g., `KSPCreate()`.
4003 
4004 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4005 @*/
4006 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4007 {
4008   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4009 
4010   PetscFunctionBegin;
4011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4012   PetscValidType(mat, 1);
4013   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4014   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4015   PetscCheckSameComm(mat, 1, b, 2);
4016   PetscCheckSameComm(mat, 1, x, 3);
4017   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4018   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);
4019   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);
4020   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4021   MatCheckPreallocated(mat, 1);
4022   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4023   if (mat->factorerrortype) {
4024     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4025     PetscCall(VecSetInf(x));
4026   } else {
4027     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4028     PetscCall((*f)(mat, b, x));
4029   }
4030   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4031   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4032   PetscFunctionReturn(PETSC_SUCCESS);
4033 }
4034 
4035 /*@
4036    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4037                       factored matrix.
4038 
4039    Neighbor-wise Collective
4040 
4041    Input Parameters:
4042 +  mat - the factored matrix
4043 .  b - the right-hand-side vector
4044 -  y - the vector to be added to
4045 
4046    Output Parameter:
4047 .  x - the result vector
4048 
4049    Level: developer
4050 
4051    Note:
4052    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4053    call `MatSolveTransposeAdd`(A,x,y,x).
4054 
4055 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4056 @*/
4057 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4058 {
4059   PetscScalar one = 1.0;
4060   Vec         tmp;
4061   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4062 
4063   PetscFunctionBegin;
4064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4065   PetscValidType(mat, 1);
4066   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4067   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4068   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4069   PetscCheckSameComm(mat, 1, b, 2);
4070   PetscCheckSameComm(mat, 1, y, 3);
4071   PetscCheckSameComm(mat, 1, x, 4);
4072   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4073   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);
4074   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);
4075   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);
4076   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);
4077   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4078   MatCheckPreallocated(mat, 1);
4079 
4080   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4081   if (mat->factorerrortype) {
4082     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4083     PetscCall(VecSetInf(x));
4084   } else if (f) {
4085     PetscCall((*f)(mat, b, y, x));
4086   } else {
4087     /* do the solve then the add manually */
4088     if (x != y) {
4089       PetscCall(MatSolveTranspose(mat, b, x));
4090       PetscCall(VecAXPY(x, one, y));
4091     } else {
4092       PetscCall(VecDuplicate(x, &tmp));
4093       PetscCall(VecCopy(x, tmp));
4094       PetscCall(MatSolveTranspose(mat, b, x));
4095       PetscCall(VecAXPY(x, one, tmp));
4096       PetscCall(VecDestroy(&tmp));
4097     }
4098   }
4099   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4100   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4101   PetscFunctionReturn(PETSC_SUCCESS);
4102 }
4103 
4104 /*@
4105    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4106 
4107    Neighbor-wise Collective
4108 
4109    Input Parameters:
4110 +  mat - the matrix
4111 .  b - the right hand side
4112 .  omega - the relaxation factor
4113 .  flag - flag indicating the type of SOR (see below)
4114 .  shift -  diagonal shift
4115 .  its - the number of iterations
4116 -  lits - the number of local iterations
4117 
4118    Output Parameter:
4119 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4120 
4121    SOR Flags:
4122 +     `SOR_FORWARD_SWEEP` - forward SOR
4123 .     `SOR_BACKWARD_SWEEP` - backward SOR
4124 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4125 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4126 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4127 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4128 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4129 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4130          upper/lower triangular part of matrix to
4131          vector (with omega)
4132 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4133 
4134    Level: developer
4135 
4136    Notes:
4137    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4138    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4139    on each processor.
4140 
4141    Application programmers will not generally use `MatSOR()` directly,
4142    but instead will employ the `KSP`/`PC` interface.
4143 
4144    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4145 
4146    Most users should employ the `KSP` interface for linear solvers
4147    instead of working directly with matrix algebra routines such as this.
4148    See, e.g., `KSPCreate()`.
4149 
4150    Vectors `x` and `b` CANNOT be the same
4151 
4152    The flags are implemented as bitwise inclusive or operations.
4153    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4154    to specify a zero initial guess for SSOR.
4155 
4156    Developer Note:
4157    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4158 
4159 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4160 @*/
4161 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4162 {
4163   PetscFunctionBegin;
4164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4165   PetscValidType(mat, 1);
4166   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4167   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4168   PetscCheckSameComm(mat, 1, b, 2);
4169   PetscCheckSameComm(mat, 1, x, 8);
4170   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4171   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4172   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);
4173   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);
4174   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);
4175   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4176   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4177   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4178 
4179   MatCheckPreallocated(mat, 1);
4180   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4181   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4182   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4183   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4184   PetscFunctionReturn(PETSC_SUCCESS);
4185 }
4186 
4187 /*
4188       Default matrix copy routine.
4189 */
4190 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4191 {
4192   PetscInt           i, rstart = 0, rend = 0, nz;
4193   const PetscInt    *cwork;
4194   const PetscScalar *vwork;
4195 
4196   PetscFunctionBegin;
4197   if (B->assembled) PetscCall(MatZeroEntries(B));
4198   if (str == SAME_NONZERO_PATTERN) {
4199     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4200     for (i = rstart; i < rend; i++) {
4201       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4202       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4203       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4204     }
4205   } else {
4206     PetscCall(MatAYPX(B, 0.0, A, str));
4207   }
4208   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4209   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4210   PetscFunctionReturn(PETSC_SUCCESS);
4211 }
4212 
4213 /*@
4214    MatCopy - Copies a matrix to another matrix.
4215 
4216    Collective
4217 
4218    Input Parameters:
4219 +  A - the matrix
4220 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4221 
4222    Output Parameter:
4223 .  B - where the copy is put
4224 
4225    Level: intermediate
4226 
4227    Notes:
4228    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4229 
4230    `MatCopy()` copies the matrix entries of a matrix to another existing
4231    matrix (after first zeroing the second matrix).  A related routine is
4232    `MatConvert()`, which first creates a new matrix and then copies the data.
4233 
4234 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4235 @*/
4236 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4237 {
4238   PetscInt i;
4239 
4240   PetscFunctionBegin;
4241   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4242   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4243   PetscValidType(A, 1);
4244   PetscValidType(B, 2);
4245   PetscCheckSameComm(A, 1, B, 2);
4246   MatCheckPreallocated(B, 2);
4247   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4248   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4249   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,
4250              A->cmap->N, B->cmap->N);
4251   MatCheckPreallocated(A, 1);
4252   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4253 
4254   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4255   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4256   else PetscCall(MatCopy_Basic(A, B, str));
4257 
4258   B->stencil.dim = A->stencil.dim;
4259   B->stencil.noc = A->stencil.noc;
4260   for (i = 0; i <= A->stencil.dim; i++) {
4261     B->stencil.dims[i]   = A->stencil.dims[i];
4262     B->stencil.starts[i] = A->stencil.starts[i];
4263   }
4264 
4265   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4266   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4267   PetscFunctionReturn(PETSC_SUCCESS);
4268 }
4269 
4270 /*@C
4271    MatConvert - Converts a matrix to another matrix, either of the same
4272    or different type.
4273 
4274    Collective
4275 
4276    Input Parameters:
4277 +  mat - the matrix
4278 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4279    same type as the original matrix.
4280 -  reuse - denotes if the destination matrix is to be created or reused.
4281    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
4282    `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).
4283 
4284    Output Parameter:
4285 .  M - pointer to place new matrix
4286 
4287    Level: intermediate
4288 
4289    Notes:
4290    `MatConvert()` first creates a new matrix and then copies the data from
4291    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4292    entries of one matrix to another already existing matrix context.
4293 
4294    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4295    the MPI communicator of the generated matrix is always the same as the communicator
4296    of the input matrix.
4297 
4298 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4299 @*/
4300 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4301 {
4302   PetscBool  sametype, issame, flg;
4303   PetscBool3 issymmetric, ishermitian;
4304   char       convname[256], mtype[256];
4305   Mat        B;
4306 
4307   PetscFunctionBegin;
4308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4309   PetscValidType(mat, 1);
4310   PetscValidPointer(M, 4);
4311   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4312   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4313   MatCheckPreallocated(mat, 1);
4314 
4315   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4316   if (flg) newtype = mtype;
4317 
4318   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4319   PetscCall(PetscStrcmp(newtype, "same", &issame));
4320   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4321   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");
4322 
4323   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4324     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4325     PetscFunctionReturn(PETSC_SUCCESS);
4326   }
4327 
4328   /* Cache Mat options because some converters use MatHeaderReplace  */
4329   issymmetric = mat->symmetric;
4330   ishermitian = mat->hermitian;
4331 
4332   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4333     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4334     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4335   } else {
4336     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4337     const char *prefix[3]                                 = {"seq", "mpi", ""};
4338     PetscInt    i;
4339     /*
4340        Order of precedence:
4341        0) See if newtype is a superclass of the current matrix.
4342        1) See if a specialized converter is known to the current matrix.
4343        2) See if a specialized converter is known to the desired matrix class.
4344        3) See if a good general converter is registered for the desired class
4345           (as of 6/27/03 only MATMPIADJ falls into this category).
4346        4) See if a good general converter is known for the current matrix.
4347        5) Use a really basic converter.
4348     */
4349 
4350     /* 0) See if newtype is a superclass of the current matrix.
4351           i.e mat is mpiaij and newtype is aij */
4352     for (i = 0; i < 2; i++) {
4353       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4354       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4355       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4356       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4357       if (flg) {
4358         if (reuse == MAT_INPLACE_MATRIX) {
4359           PetscCall(PetscInfo(mat, "Early return\n"));
4360           PetscFunctionReturn(PETSC_SUCCESS);
4361         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4362           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4363           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4364           PetscFunctionReturn(PETSC_SUCCESS);
4365         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4366           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4367           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4368           PetscFunctionReturn(PETSC_SUCCESS);
4369         }
4370       }
4371     }
4372     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4373     for (i = 0; i < 3; i++) {
4374       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4381       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4382       if (conv) goto foundconv;
4383     }
4384 
4385     /* 2)  See if a specialized converter is known to the desired matrix class. */
4386     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4387     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4388     PetscCall(MatSetType(B, newtype));
4389     for (i = 0; i < 3; i++) {
4390       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4396       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4397       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4398       if (conv) {
4399         PetscCall(MatDestroy(&B));
4400         goto foundconv;
4401       }
4402     }
4403 
4404     /* 3) See if a good general converter is registered for the desired class */
4405     conv = B->ops->convertfrom;
4406     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4407     PetscCall(MatDestroy(&B));
4408     if (conv) goto foundconv;
4409 
4410     /* 4) See if a good general converter is known for the current matrix */
4411     if (mat->ops->convert) conv = mat->ops->convert;
4412     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4413     if (conv) goto foundconv;
4414 
4415     /* 5) Use a really basic converter. */
4416     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4417     conv = MatConvert_Basic;
4418 
4419   foundconv:
4420     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4421     PetscCall((*conv)(mat, newtype, reuse, M));
4422     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4423       /* the block sizes must be same if the mappings are copied over */
4424       (*M)->rmap->bs = mat->rmap->bs;
4425       (*M)->cmap->bs = mat->cmap->bs;
4426       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4427       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4428       (*M)->rmap->mapping = mat->rmap->mapping;
4429       (*M)->cmap->mapping = mat->cmap->mapping;
4430     }
4431     (*M)->stencil.dim = mat->stencil.dim;
4432     (*M)->stencil.noc = mat->stencil.noc;
4433     for (i = 0; i <= mat->stencil.dim; i++) {
4434       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4435       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4436     }
4437     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4438   }
4439   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4440 
4441   /* Copy Mat options */
4442   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4443   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4444   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4445   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4446   PetscFunctionReturn(PETSC_SUCCESS);
4447 }
4448 
4449 /*@C
4450    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4451 
4452    Not Collective
4453 
4454    Input Parameter:
4455 .  mat - the matrix, must be a factored matrix
4456 
4457    Output Parameter:
4458 .   type - the string name of the package (do not free this string)
4459 
4460    Level: intermediate
4461 
4462    Fortran Note:
4463    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4464 
4465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4466 @*/
4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4468 {
4469   PetscErrorCode (*conv)(Mat, MatSolverType *);
4470 
4471   PetscFunctionBegin;
4472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4473   PetscValidType(mat, 1);
4474   PetscValidPointer(type, 2);
4475   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4476   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4477   if (conv) PetscCall((*conv)(mat, type));
4478   else *type = MATSOLVERPETSC;
4479   PetscFunctionReturn(PETSC_SUCCESS);
4480 }
4481 
4482 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4483 struct _MatSolverTypeForSpecifcType {
4484   MatType mtype;
4485   /* no entry for MAT_FACTOR_NONE */
4486   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4487   MatSolverTypeForSpecifcType next;
4488 };
4489 
4490 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4491 struct _MatSolverTypeHolder {
4492   char                       *name;
4493   MatSolverTypeForSpecifcType handlers;
4494   MatSolverTypeHolder         next;
4495 };
4496 
4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4498 
4499 /*@C
4500    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4501 
4502    Input Parameters:
4503 +    package - name of the package, for example petsc or superlu
4504 .    mtype - the matrix type that works with this package
4505 .    ftype - the type of factorization supported by the package
4506 -    createfactor - routine that will create the factored matrix ready to be used
4507 
4508     Level: developer
4509 
4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4511 @*/
4512 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4513 {
4514   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4515   PetscBool                   flg;
4516   MatSolverTypeForSpecifcType inext, iprev = NULL;
4517 
4518   PetscFunctionBegin;
4519   PetscCall(MatInitializePackage());
4520   if (!next) {
4521     PetscCall(PetscNew(&MatSolverTypeHolders));
4522     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4523     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4524     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4525     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4526     PetscFunctionReturn(PETSC_SUCCESS);
4527   }
4528   while (next) {
4529     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4530     if (flg) {
4531       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4532       inext = next->handlers;
4533       while (inext) {
4534         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4535         if (flg) {
4536           inext->createfactor[(int)ftype - 1] = createfactor;
4537           PetscFunctionReturn(PETSC_SUCCESS);
4538         }
4539         iprev = inext;
4540         inext = inext->next;
4541       }
4542       PetscCall(PetscNew(&iprev->next));
4543       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4544       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4545       PetscFunctionReturn(PETSC_SUCCESS);
4546     }
4547     prev = next;
4548     next = next->next;
4549   }
4550   PetscCall(PetscNew(&prev->next));
4551   PetscCall(PetscStrallocpy(package, &prev->next->name));
4552   PetscCall(PetscNew(&prev->next->handlers));
4553   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4554   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4555   PetscFunctionReturn(PETSC_SUCCESS);
4556 }
4557 
4558 /*@C
4559    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4560 
4561    Input Parameters:
4562 +    type - name of the package, for example petsc or superlu
4563 .    ftype - the type of factorization supported by the type
4564 -    mtype - the matrix type that works with this type
4565 
4566    Output Parameters:
4567 +   foundtype - `PETSC_TRUE` if the type was registered
4568 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4569 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4570 
4571     Level: developer
4572 
4573 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4574 @*/
4575 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4576 {
4577   MatSolverTypeHolder         next = MatSolverTypeHolders;
4578   PetscBool                   flg;
4579   MatSolverTypeForSpecifcType inext;
4580 
4581   PetscFunctionBegin;
4582   if (foundtype) *foundtype = PETSC_FALSE;
4583   if (foundmtype) *foundmtype = PETSC_FALSE;
4584   if (createfactor) *createfactor = NULL;
4585 
4586   if (type) {
4587     while (next) {
4588       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4589       if (flg) {
4590         if (foundtype) *foundtype = PETSC_TRUE;
4591         inext = next->handlers;
4592         while (inext) {
4593           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4594           if (flg) {
4595             if (foundmtype) *foundmtype = PETSC_TRUE;
4596             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4597             PetscFunctionReturn(PETSC_SUCCESS);
4598           }
4599           inext = inext->next;
4600         }
4601       }
4602       next = next->next;
4603     }
4604   } else {
4605     while (next) {
4606       inext = next->handlers;
4607       while (inext) {
4608         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4609         if (flg && inext->createfactor[(int)ftype - 1]) {
4610           if (foundtype) *foundtype = PETSC_TRUE;
4611           if (foundmtype) *foundmtype = PETSC_TRUE;
4612           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4613           PetscFunctionReturn(PETSC_SUCCESS);
4614         }
4615         inext = inext->next;
4616       }
4617       next = next->next;
4618     }
4619     /* try with base classes inext->mtype */
4620     next = MatSolverTypeHolders;
4621     while (next) {
4622       inext = next->handlers;
4623       while (inext) {
4624         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4625         if (flg && inext->createfactor[(int)ftype - 1]) {
4626           if (foundtype) *foundtype = PETSC_TRUE;
4627           if (foundmtype) *foundmtype = PETSC_TRUE;
4628           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4629           PetscFunctionReturn(PETSC_SUCCESS);
4630         }
4631         inext = inext->next;
4632       }
4633       next = next->next;
4634     }
4635   }
4636   PetscFunctionReturn(PETSC_SUCCESS);
4637 }
4638 
4639 PetscErrorCode MatSolverTypeDestroy(void)
4640 {
4641   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4642   MatSolverTypeForSpecifcType inext, iprev;
4643 
4644   PetscFunctionBegin;
4645   while (next) {
4646     PetscCall(PetscFree(next->name));
4647     inext = next->handlers;
4648     while (inext) {
4649       PetscCall(PetscFree(inext->mtype));
4650       iprev = inext;
4651       inext = inext->next;
4652       PetscCall(PetscFree(iprev));
4653     }
4654     prev = next;
4655     next = next->next;
4656     PetscCall(PetscFree(prev));
4657   }
4658   MatSolverTypeHolders = NULL;
4659   PetscFunctionReturn(PETSC_SUCCESS);
4660 }
4661 
4662 /*@C
4663    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4664 
4665    Logically Collective
4666 
4667    Input Parameter:
4668 .  mat - the matrix
4669 
4670    Output Parameter:
4671 .  flg - `PETSC_TRUE` if uses the ordering
4672 
4673    Level: developer
4674 
4675    Note:
4676    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4677    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4678 
4679 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4680 @*/
4681 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4682 {
4683   PetscFunctionBegin;
4684   *flg = mat->canuseordering;
4685   PetscFunctionReturn(PETSC_SUCCESS);
4686 }
4687 
4688 /*@C
4689    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4690 
4691    Logically Collective
4692 
4693    Input Parameters:
4694 +  mat - the matrix obtained with `MatGetFactor()`
4695 -  ftype - the factorization type to be used
4696 
4697    Output Parameter:
4698 .  otype - the preferred ordering type
4699 
4700    Level: developer
4701 
4702 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4703 @*/
4704 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4705 {
4706   PetscFunctionBegin;
4707   *otype = mat->preferredordering[ftype];
4708   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4709   PetscFunctionReturn(PETSC_SUCCESS);
4710 }
4711 
4712 /*@C
4713    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4714 
4715    Collective
4716 
4717    Input Parameters:
4718 +  mat - the matrix
4719 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4720 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4721 
4722    Output Parameter:
4723 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4724 
4725    Options Database Key:
4726 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4727                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4728 
4729    Level: intermediate
4730 
4731    Notes:
4732      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4733      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4734 
4735      Users usually access the factorization solvers via `KSP`
4736 
4737       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4738      such as pastix, superlu, mumps etc.
4739 
4740       PETSc must have been ./configure to use the external solver, using the option --download-package
4741 
4742       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4743       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4744       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4745 
4746    Developer Note:
4747       This should actually be called `MatCreateFactor()` since it creates a new factor object
4748 
4749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4750           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4751 @*/
4752 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4753 {
4754   PetscBool foundtype, foundmtype;
4755   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4756 
4757   PetscFunctionBegin;
4758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4759   PetscValidType(mat, 1);
4760 
4761   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4762   MatCheckPreallocated(mat, 1);
4763 
4764   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4765   if (!foundtype) {
4766     if (type) {
4767       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],
4768               ((PetscObject)mat)->type_name, type);
4769     } else {
4770       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);
4771     }
4772   }
4773   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4774   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);
4775 
4776   PetscCall((*conv)(mat, ftype, f));
4777   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4778   PetscFunctionReturn(PETSC_SUCCESS);
4779 }
4780 
4781 /*@C
4782    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4783 
4784    Not Collective
4785 
4786    Input Parameters:
4787 +  mat - the matrix
4788 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4789 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4790 
4791    Output Parameter:
4792 .    flg - PETSC_TRUE if the factorization is available
4793 
4794    Level: intermediate
4795 
4796    Notes:
4797       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4798      such as pastix, superlu, mumps etc.
4799 
4800       PETSc must have been ./configure to use the external solver, using the option --download-package
4801 
4802    Developer Note:
4803       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4804 
4805 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4806           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4807 @*/
4808 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4809 {
4810   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4811 
4812   PetscFunctionBegin;
4813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4814   PetscValidType(mat, 1);
4815   PetscValidBoolPointer(flg, 4);
4816 
4817   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4818   MatCheckPreallocated(mat, 1);
4819 
4820   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4821   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4822   PetscFunctionReturn(PETSC_SUCCESS);
4823 }
4824 
4825 /*@
4826    MatDuplicate - Duplicates a matrix including the non-zero structure.
4827 
4828    Collective
4829 
4830    Input Parameters:
4831 +  mat - the matrix
4832 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4833         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4834 
4835    Output Parameter:
4836 .  M - pointer to place new matrix
4837 
4838    Level: intermediate
4839 
4840    Notes:
4841     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4842 
4843     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.
4844 
4845     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
4846     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4847     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4848 
4849 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4850 @*/
4851 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4852 {
4853   Mat         B;
4854   VecType     vtype;
4855   PetscInt    i;
4856   PetscObject dm, container_h, container_d;
4857   void (*viewf)(void);
4858 
4859   PetscFunctionBegin;
4860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4861   PetscValidType(mat, 1);
4862   PetscValidPointer(M, 3);
4863   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4864   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4865   MatCheckPreallocated(mat, 1);
4866 
4867   *M = NULL;
4868   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4869   PetscUseTypeMethod(mat, duplicate, op, M);
4870   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4871   B = *M;
4872 
4873   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4874   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4875   PetscCall(MatGetVecType(mat, &vtype));
4876   PetscCall(MatSetVecType(B, vtype));
4877 
4878   B->stencil.dim = mat->stencil.dim;
4879   B->stencil.noc = mat->stencil.noc;
4880   for (i = 0; i <= mat->stencil.dim; i++) {
4881     B->stencil.dims[i]   = mat->stencil.dims[i];
4882     B->stencil.starts[i] = mat->stencil.starts[i];
4883   }
4884 
4885   B->nooffproczerorows = mat->nooffproczerorows;
4886   B->nooffprocentries  = mat->nooffprocentries;
4887 
4888   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4889   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4890   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4891   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4892   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4893   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4894   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4895   PetscFunctionReturn(PETSC_SUCCESS);
4896 }
4897 
4898 /*@
4899    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4900 
4901    Logically Collective
4902 
4903    Input Parameter:
4904 .  mat - the matrix
4905 
4906    Output Parameter:
4907 .  v - the diagonal of the matrix
4908 
4909    Level: intermediate
4910 
4911    Note:
4912    If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4913    of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4914    is larger than `ndiag`, the values of the remaining entries are unspecified.
4915 
4916    Currently only correct in parallel for square matrices.
4917 
4918 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4919 @*/
4920 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4921 {
4922   PetscFunctionBegin;
4923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4924   PetscValidType(mat, 1);
4925   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4926   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4927   MatCheckPreallocated(mat, 1);
4928   if (PetscDefined(USE_DEBUG)) {
4929     PetscInt nv, row, col, ndiag;
4930 
4931     PetscCall(VecGetLocalSize(v, &nv));
4932     PetscCall(MatGetLocalSize(mat, &row, &col));
4933     ndiag = PetscMin(row, col);
4934     PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
4935   }
4936 
4937   PetscUseTypeMethod(mat, getdiagonal, v);
4938   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4939   PetscFunctionReturn(PETSC_SUCCESS);
4940 }
4941 
4942 /*@C
4943    MatGetRowMin - Gets the minimum value (of the real part) of each
4944         row of the matrix
4945 
4946    Logically Collective
4947 
4948    Input Parameter:
4949 .  mat - the matrix
4950 
4951    Output Parameters:
4952 +  v - the vector for storing the maximums
4953 -  idx - the indices of the column found for each row (optional)
4954 
4955    Level: intermediate
4956 
4957    Note:
4958     The result of this call are the same as if one converted the matrix to dense format
4959       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4960 
4961     This code is only implemented for a couple of matrix formats.
4962 
4963 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4964           `MatGetRowMax()`
4965 @*/
4966 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4967 {
4968   PetscFunctionBegin;
4969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4970   PetscValidType(mat, 1);
4971   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4972   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4973 
4974   if (!mat->cmap->N) {
4975     PetscCall(VecSet(v, PETSC_MAX_REAL));
4976     if (idx) {
4977       PetscInt i, m = mat->rmap->n;
4978       for (i = 0; i < m; i++) idx[i] = -1;
4979     }
4980   } else {
4981     MatCheckPreallocated(mat, 1);
4982   }
4983   PetscUseTypeMethod(mat, getrowmin, v, idx);
4984   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4985   PetscFunctionReturn(PETSC_SUCCESS);
4986 }
4987 
4988 /*@C
4989    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4990         row of the matrix
4991 
4992    Logically Collective
4993 
4994    Input Parameter:
4995 .  mat - the matrix
4996 
4997    Output Parameters:
4998 +  v - the vector for storing the minimums
4999 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5000 
5001    Level: intermediate
5002 
5003    Notes:
5004     if a row is completely empty or has only 0.0 values then the idx[] value for that
5005     row is 0 (the first column).
5006 
5007     This code is only implemented for a couple of matrix formats.
5008 
5009 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5010 @*/
5011 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5012 {
5013   PetscFunctionBegin;
5014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5015   PetscValidType(mat, 1);
5016   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5017   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5018   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5019 
5020   if (!mat->cmap->N) {
5021     PetscCall(VecSet(v, 0.0));
5022     if (idx) {
5023       PetscInt i, m = mat->rmap->n;
5024       for (i = 0; i < m; i++) idx[i] = -1;
5025     }
5026   } else {
5027     MatCheckPreallocated(mat, 1);
5028     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5029     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5030   }
5031   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5032   PetscFunctionReturn(PETSC_SUCCESS);
5033 }
5034 
5035 /*@C
5036    MatGetRowMax - Gets the maximum value (of the real part) of each
5037         row of the matrix
5038 
5039    Logically Collective
5040 
5041    Input Parameter:
5042 .  mat - the matrix
5043 
5044    Output Parameters:
5045 +  v - the vector for storing the maximums
5046 -  idx - the indices of the column found for each row (optional)
5047 
5048    Level: intermediate
5049 
5050    Notes:
5051     The result of this call are the same as if one converted the matrix to dense format
5052       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5053 
5054     This code is only implemented for a couple of matrix formats.
5055 
5056 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5057 @*/
5058 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5059 {
5060   PetscFunctionBegin;
5061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5062   PetscValidType(mat, 1);
5063   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5065 
5066   if (!mat->cmap->N) {
5067     PetscCall(VecSet(v, PETSC_MIN_REAL));
5068     if (idx) {
5069       PetscInt i, m = mat->rmap->n;
5070       for (i = 0; i < m; i++) idx[i] = -1;
5071     }
5072   } else {
5073     MatCheckPreallocated(mat, 1);
5074     PetscUseTypeMethod(mat, getrowmax, v, idx);
5075   }
5076   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5077   PetscFunctionReturn(PETSC_SUCCESS);
5078 }
5079 
5080 /*@C
5081    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5082         row of the matrix
5083 
5084    Logically Collective
5085 
5086    Input Parameter:
5087 .  mat - the matrix
5088 
5089    Output Parameters:
5090 +  v - the vector for storing the maximums
5091 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5092 
5093    Level: intermediate
5094 
5095    Notes:
5096     if a row is completely empty or has only 0.0 values then the idx[] value for that
5097     row is 0 (the first column).
5098 
5099     This code is only implemented for a couple of matrix formats.
5100 
5101 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5102 @*/
5103 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5104 {
5105   PetscFunctionBegin;
5106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5107   PetscValidType(mat, 1);
5108   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5109   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5110 
5111   if (!mat->cmap->N) {
5112     PetscCall(VecSet(v, 0.0));
5113     if (idx) {
5114       PetscInt i, m = mat->rmap->n;
5115       for (i = 0; i < m; i++) idx[i] = -1;
5116     }
5117   } else {
5118     MatCheckPreallocated(mat, 1);
5119     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5120     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5121   }
5122   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5123   PetscFunctionReturn(PETSC_SUCCESS);
5124 }
5125 
5126 /*@
5127    MatGetRowSum - Gets the sum of each row of the matrix
5128 
5129    Logically or Neighborhood Collective
5130 
5131    Input Parameter:
5132 .  mat - the matrix
5133 
5134    Output Parameter:
5135 .  v - the vector for storing the sum of rows
5136 
5137    Level: intermediate
5138 
5139    Notes:
5140     This code is slow since it is not currently specialized for different formats
5141 
5142 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5143 @*/
5144 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5145 {
5146   Vec ones;
5147 
5148   PetscFunctionBegin;
5149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5150   PetscValidType(mat, 1);
5151   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5153   MatCheckPreallocated(mat, 1);
5154   PetscCall(MatCreateVecs(mat, &ones, NULL));
5155   PetscCall(VecSet(ones, 1.));
5156   PetscCall(MatMult(mat, ones, v));
5157   PetscCall(VecDestroy(&ones));
5158   PetscFunctionReturn(PETSC_SUCCESS);
5159 }
5160 
5161 /*@
5162    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5163    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5164 
5165    Collective
5166 
5167    Input Parameter:
5168 .  mat - the matrix to provide the transpose
5169 
5170    Output Parameter:
5171 .  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
5172 
5173    Level: advanced
5174 
5175    Note:
5176    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
5177    routine allows bypassing that call.
5178 
5179 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5180 @*/
5181 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5182 {
5183   PetscContainer  rB = NULL;
5184   MatParentState *rb = NULL;
5185 
5186   PetscFunctionBegin;
5187   PetscCall(PetscNew(&rb));
5188   rb->id    = ((PetscObject)mat)->id;
5189   rb->state = 0;
5190   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5191   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5192   PetscCall(PetscContainerSetPointer(rB, rb));
5193   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5194   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5195   PetscCall(PetscObjectDereference((PetscObject)rB));
5196   PetscFunctionReturn(PETSC_SUCCESS);
5197 }
5198 
5199 /*@
5200    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5201 
5202    Collective
5203 
5204    Input Parameters:
5205 +  mat - the matrix to transpose
5206 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5207 
5208    Output Parameter:
5209 .  B - the transpose
5210 
5211    Level: intermediate
5212 
5213    Notes:
5214      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5215 
5216      `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
5217      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5218 
5219      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.
5220 
5221      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5222 
5223      If mat is unchanged from the last call this function returns immediately without recomputing the result
5224 
5225      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5226 
5227 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5228           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5229 @*/
5230 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5231 {
5232   PetscContainer  rB = NULL;
5233   MatParentState *rb = NULL;
5234 
5235   PetscFunctionBegin;
5236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5237   PetscValidType(mat, 1);
5238   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5239   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5240   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5241   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5242   MatCheckPreallocated(mat, 1);
5243   if (reuse == MAT_REUSE_MATRIX) {
5244     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5245     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5246     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5247     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5248     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5249   }
5250 
5251   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5252   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5253     PetscUseTypeMethod(mat, transpose, reuse, B);
5254     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5255   }
5256   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5257 
5258   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5259   if (reuse != MAT_INPLACE_MATRIX) {
5260     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5261     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5262     rb->state        = ((PetscObject)mat)->state;
5263     rb->nonzerostate = mat->nonzerostate;
5264   }
5265   PetscFunctionReturn(PETSC_SUCCESS);
5266 }
5267 
5268 /*@
5269    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5270 
5271    Collective
5272 
5273    Input Parameter:
5274 .  A - the matrix to transpose
5275 
5276    Output Parameter:
5277 .  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
5278       numerical portion.
5279 
5280    Level: intermediate
5281 
5282    Note:
5283    This is not supported for many matrix types, use `MatTranspose()` in those cases
5284 
5285 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5286 @*/
5287 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5288 {
5289   PetscFunctionBegin;
5290   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5291   PetscValidType(A, 1);
5292   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5293   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5294   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5295   PetscUseTypeMethod(A, transposesymbolic, B);
5296   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5297 
5298   PetscCall(MatTransposeSetPrecursor(A, *B));
5299   PetscFunctionReturn(PETSC_SUCCESS);
5300 }
5301 
5302 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5303 {
5304   PetscContainer  rB;
5305   MatParentState *rb;
5306 
5307   PetscFunctionBegin;
5308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5309   PetscValidType(A, 1);
5310   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5311   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5312   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5313   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5314   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5315   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5316   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5317   PetscFunctionReturn(PETSC_SUCCESS);
5318 }
5319 
5320 /*@
5321    MatIsTranspose - Test whether a matrix is another one's transpose,
5322         or its own, in which case it tests symmetry.
5323 
5324    Collective
5325 
5326    Input Parameters:
5327 +  A - the matrix to test
5328 .  B - the matrix to test against, this can equal the first parameter
5329 -  tol - tolerance, differences between entries smaller than this are counted as zero
5330 
5331    Output Parameter:
5332 .  flg - the result
5333 
5334    Level: intermediate
5335 
5336    Notes:
5337    Only available for `MATAIJ` matrices.
5338 
5339    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5340    test involves parallel copies of the block-offdiagonal parts of the matrix.
5341 
5342 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5343 @*/
5344 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5345 {
5346   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5347 
5348   PetscFunctionBegin;
5349   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5350   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5351   PetscValidBoolPointer(flg, 4);
5352   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5353   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5354   *flg = PETSC_FALSE;
5355   if (f && g) {
5356     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5357     PetscCall((*f)(A, B, tol, flg));
5358   } else {
5359     MatType mattype;
5360 
5361     PetscCall(MatGetType(f ? B : A, &mattype));
5362     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5363   }
5364   PetscFunctionReturn(PETSC_SUCCESS);
5365 }
5366 
5367 /*@
5368    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5369 
5370    Collective
5371 
5372    Input Parameters:
5373 +  mat - the matrix to transpose and complex conjugate
5374 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5375 
5376    Output Parameter:
5377 .  B - the Hermitian transpose
5378 
5379    Level: intermediate
5380 
5381 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5382 @*/
5383 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5384 {
5385   PetscFunctionBegin;
5386   PetscCall(MatTranspose(mat, reuse, B));
5387 #if defined(PETSC_USE_COMPLEX)
5388   PetscCall(MatConjugate(*B));
5389 #endif
5390   PetscFunctionReturn(PETSC_SUCCESS);
5391 }
5392 
5393 /*@
5394    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5395 
5396    Collective
5397 
5398    Input Parameters:
5399 +  A - the matrix to test
5400 .  B - the matrix to test against, this can equal the first parameter
5401 -  tol - tolerance, differences between entries smaller than this are counted as zero
5402 
5403    Output Parameter:
5404 .  flg - the result
5405 
5406    Level: intermediate
5407 
5408    Notes:
5409    Only available for `MATAIJ` matrices.
5410 
5411    The sequential algorithm
5412    has a running time of the order of the number of nonzeros; the parallel
5413    test involves parallel copies of the block-offdiagonal parts of the matrix.
5414 
5415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5416 @*/
5417 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5418 {
5419   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5420 
5421   PetscFunctionBegin;
5422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5423   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5424   PetscValidBoolPointer(flg, 4);
5425   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5426   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5427   if (f && g) {
5428     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5429     PetscCall((*f)(A, B, tol, flg));
5430   }
5431   PetscFunctionReturn(PETSC_SUCCESS);
5432 }
5433 
5434 /*@
5435    MatPermute - Creates a new matrix with rows and columns permuted from the
5436    original.
5437 
5438    Collective
5439 
5440    Input Parameters:
5441 +  mat - the matrix to permute
5442 .  row - row permutation, each processor supplies only the permutation for its rows
5443 -  col - column permutation, each processor supplies only the permutation for its columns
5444 
5445    Output Parameter:
5446 .  B - the permuted matrix
5447 
5448    Level: advanced
5449 
5450    Note:
5451    The index sets map from row/col of permuted matrix to row/col of original matrix.
5452    The index sets should be on the same communicator as mat and have the same local sizes.
5453 
5454    Developer Note:
5455      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5456      exploit the fact that row and col are permutations, consider implementing the
5457      more general `MatCreateSubMatrix()` instead.
5458 
5459 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5460 @*/
5461 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5462 {
5463   PetscFunctionBegin;
5464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5465   PetscValidType(mat, 1);
5466   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5467   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5468   PetscValidPointer(B, 4);
5469   PetscCheckSameComm(mat, 1, row, 2);
5470   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5471   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5472   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5473   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5474   MatCheckPreallocated(mat, 1);
5475 
5476   if (mat->ops->permute) {
5477     PetscUseTypeMethod(mat, permute, row, col, B);
5478     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5479   } else {
5480     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5481   }
5482   PetscFunctionReturn(PETSC_SUCCESS);
5483 }
5484 
5485 /*@
5486    MatEqual - Compares two matrices.
5487 
5488    Collective
5489 
5490    Input Parameters:
5491 +  A - the first matrix
5492 -  B - the second matrix
5493 
5494    Output Parameter:
5495 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5496 
5497    Level: intermediate
5498 
5499 .seealso: [](ch_matrices), `Mat`
5500 @*/
5501 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5502 {
5503   PetscFunctionBegin;
5504   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5505   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5506   PetscValidType(A, 1);
5507   PetscValidType(B, 2);
5508   PetscValidBoolPointer(flg, 3);
5509   PetscCheckSameComm(A, 1, B, 2);
5510   MatCheckPreallocated(A, 1);
5511   MatCheckPreallocated(B, 2);
5512   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5513   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5514   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,
5515              B->cmap->N);
5516   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5517     PetscUseTypeMethod(A, equal, B, flg);
5518   } else {
5519     PetscCall(MatMultEqual(A, B, 10, flg));
5520   }
5521   PetscFunctionReturn(PETSC_SUCCESS);
5522 }
5523 
5524 /*@
5525    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5526    matrices that are stored as vectors.  Either of the two scaling
5527    matrices can be `NULL`.
5528 
5529    Collective
5530 
5531    Input Parameters:
5532 +  mat - the matrix to be scaled
5533 .  l - the left scaling vector (or `NULL`)
5534 -  r - the right scaling vector (or `NULL`)
5535 
5536    Level: intermediate
5537 
5538    Note:
5539    `MatDiagonalScale()` computes A = LAR, where
5540    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5541    The L scales the rows of the matrix, the R scales the columns of the matrix.
5542 
5543 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5544 @*/
5545 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5546 {
5547   PetscFunctionBegin;
5548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5549   PetscValidType(mat, 1);
5550   if (l) {
5551     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5552     PetscCheckSameComm(mat, 1, l, 2);
5553   }
5554   if (r) {
5555     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5556     PetscCheckSameComm(mat, 1, r, 3);
5557   }
5558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5559   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5560   MatCheckPreallocated(mat, 1);
5561   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5562 
5563   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5564   PetscUseTypeMethod(mat, diagonalscale, l, r);
5565   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5566   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5567   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5568   PetscFunctionReturn(PETSC_SUCCESS);
5569 }
5570 
5571 /*@
5572     MatScale - Scales all elements of a matrix by a given number.
5573 
5574     Logically Collective
5575 
5576     Input Parameters:
5577 +   mat - the matrix to be scaled
5578 -   a  - the scaling value
5579 
5580     Level: intermediate
5581 
5582 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5583 @*/
5584 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5585 {
5586   PetscFunctionBegin;
5587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5588   PetscValidType(mat, 1);
5589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5591   PetscValidLogicalCollectiveScalar(mat, a, 2);
5592   MatCheckPreallocated(mat, 1);
5593 
5594   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5595   if (a != (PetscScalar)1.0) {
5596     PetscUseTypeMethod(mat, scale, a);
5597     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5598   }
5599   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5600   PetscFunctionReturn(PETSC_SUCCESS);
5601 }
5602 
5603 /*@
5604    MatNorm - Calculates various norms of a matrix.
5605 
5606    Collective
5607 
5608    Input Parameters:
5609 +  mat - the matrix
5610 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5611 
5612    Output Parameter:
5613 .  nrm - the resulting norm
5614 
5615    Level: intermediate
5616 
5617 .seealso: [](ch_matrices), `Mat`
5618 @*/
5619 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5620 {
5621   PetscFunctionBegin;
5622   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5623   PetscValidType(mat, 1);
5624   PetscValidRealPointer(nrm, 3);
5625 
5626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5627   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5628   MatCheckPreallocated(mat, 1);
5629 
5630   PetscUseTypeMethod(mat, norm, type, nrm);
5631   PetscFunctionReturn(PETSC_SUCCESS);
5632 }
5633 
5634 /*
5635      This variable is used to prevent counting of MatAssemblyBegin() that
5636    are called from within a MatAssemblyEnd().
5637 */
5638 static PetscInt MatAssemblyEnd_InUse = 0;
5639 /*@
5640    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5641    be called after completing all calls to `MatSetValues()`.
5642 
5643    Collective
5644 
5645    Input Parameters:
5646 +  mat - the matrix
5647 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5648 
5649    Level: beginner
5650 
5651    Notes:
5652    `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5653    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5654 
5655    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5656    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5657    using the matrix.
5658 
5659    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5660    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
5661    a global collective operation requiring all processes that share the matrix.
5662 
5663    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5664    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5665    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5666 
5667 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5668 @*/
5669 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5670 {
5671   PetscFunctionBegin;
5672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5673   PetscValidType(mat, 1);
5674   MatCheckPreallocated(mat, 1);
5675   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5676   if (mat->assembled) {
5677     mat->was_assembled = PETSC_TRUE;
5678     mat->assembled     = PETSC_FALSE;
5679   }
5680 
5681   if (!MatAssemblyEnd_InUse) {
5682     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5683     PetscTryTypeMethod(mat, assemblybegin, type);
5684     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5685   } else PetscTryTypeMethod(mat, assemblybegin, type);
5686   PetscFunctionReturn(PETSC_SUCCESS);
5687 }
5688 
5689 /*@
5690    MatAssembled - Indicates if a matrix has been assembled and is ready for
5691      use; for example, in matrix-vector product.
5692 
5693    Not Collective
5694 
5695    Input Parameter:
5696 .  mat - the matrix
5697 
5698    Output Parameter:
5699 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5700 
5701    Level: advanced
5702 
5703 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5704 @*/
5705 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5706 {
5707   PetscFunctionBegin;
5708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5709   PetscValidBoolPointer(assembled, 2);
5710   *assembled = mat->assembled;
5711   PetscFunctionReturn(PETSC_SUCCESS);
5712 }
5713 
5714 /*@
5715    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5716    be called after `MatAssemblyBegin()`.
5717 
5718    Collective
5719 
5720    Input Parameters:
5721 +  mat - the matrix
5722 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5723 
5724    Options Database Keys:
5725 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5726 .  -mat_view ::ascii_info_detail - Prints more detailed info
5727 .  -mat_view - Prints matrix in ASCII format
5728 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5729 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5730 .  -display <name> - Sets display name (default is host)
5731 .  -draw_pause <sec> - Sets number of seconds to pause after display
5732 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5733 .  -viewer_socket_machine <machine> - Machine to use for socket
5734 .  -viewer_socket_port <port> - Port number to use for socket
5735 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5736 
5737    Level: beginner
5738 
5739 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5740 @*/
5741 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5742 {
5743   static PetscInt inassm = 0;
5744   PetscBool       flg    = PETSC_FALSE;
5745 
5746   PetscFunctionBegin;
5747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5748   PetscValidType(mat, 1);
5749 
5750   inassm++;
5751   MatAssemblyEnd_InUse++;
5752   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5753     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5754     PetscTryTypeMethod(mat, assemblyend, type);
5755     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5756   } else PetscTryTypeMethod(mat, assemblyend, type);
5757 
5758   /* Flush assembly is not a true assembly */
5759   if (type != MAT_FLUSH_ASSEMBLY) {
5760     if (mat->num_ass) {
5761       if (!mat->symmetry_eternal) {
5762         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5763         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5764       }
5765       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5766       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5767     }
5768     mat->num_ass++;
5769     mat->assembled        = PETSC_TRUE;
5770     mat->ass_nonzerostate = mat->nonzerostate;
5771   }
5772 
5773   mat->insertmode = NOT_SET_VALUES;
5774   MatAssemblyEnd_InUse--;
5775   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5776   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5777     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5778 
5779     if (mat->checksymmetryonassembly) {
5780       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5781       if (flg) {
5782         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5783       } else {
5784         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5785       }
5786     }
5787     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5788   }
5789   inassm--;
5790   PetscFunctionReturn(PETSC_SUCCESS);
5791 }
5792 
5793 /*@
5794    MatSetOption - Sets a parameter option for a matrix. Some options
5795    may be specific to certain storage formats.  Some options
5796    determine how values will be inserted (or added). Sorted,
5797    row-oriented input will generally assemble the fastest. The default
5798    is row-oriented.
5799 
5800    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5801 
5802    Input Parameters:
5803 +  mat - the matrix
5804 .  option - the option, one of those listed below (and possibly others),
5805 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5806 
5807   Options Describing Matrix Structure:
5808 +    `MAT_SPD` - symmetric positive definite
5809 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5810 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5811 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5812 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5813 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5814 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5815 
5816    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5817    do not need to be computed (usually at a high cost)
5818 
5819    Options For Use with `MatSetValues()`:
5820    Insert a logically dense subblock, which can be
5821 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5822 
5823    These options reflect the data you pass in with `MatSetValues()`; it has
5824    nothing to do with how the data is stored internally in the matrix
5825    data structure.
5826 
5827    When (re)assembling a matrix, we can restrict the input for
5828    efficiency/debugging purposes.  These options include
5829 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5830 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5831 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5832 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5833 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5834 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5835         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5836         performance for very large process counts.
5837 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5838         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5839         functions, instead sending only neighbor messages.
5840 
5841    Level: intermediate
5842 
5843    Notes:
5844    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5845 
5846    Some options are relevant only for particular matrix types and
5847    are thus ignored by others.  Other options are not supported by
5848    certain matrix types and will generate an error message if set.
5849 
5850    If using Fortran to compute a matrix, one may need to
5851    use the column-oriented option (or convert to the row-oriented
5852    format).
5853 
5854    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5855    that would generate a new entry in the nonzero structure is instead
5856    ignored.  Thus, if memory has not already been allocated for this particular
5857    data, then the insertion is ignored. For dense matrices, in which
5858    the entire array is allocated, no entries are ever ignored.
5859    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5860 
5861    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5862    that would generate a new entry in the nonzero structure instead produces
5863    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
5864 
5865    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5866    that would generate a new entry that has not been preallocated will
5867    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5868    only.) This is a useful flag when debugging matrix memory preallocation.
5869    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5870 
5871    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5872    other processors should be dropped, rather than stashed.
5873    This is useful if you know that the "owning" processor is also
5874    always generating the correct matrix entries, so that PETSc need
5875    not transfer duplicate entries generated on another processor.
5876 
5877    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5878    searches during matrix assembly. When this flag is set, the hash table
5879    is created during the first matrix assembly. This hash table is
5880    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5881    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5882    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5883    supported by `MATMPIBAIJ` format only.
5884 
5885    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5886    are kept in the nonzero structure
5887 
5888    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5889    a zero location in the matrix
5890 
5891    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5892 
5893    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5894         zero row routines and thus improves performance for very large process counts.
5895 
5896    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5897         part of the matrix (since they should match the upper triangular part).
5898 
5899    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5900                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5901                      with finite difference schemes with non-periodic boundary conditions.
5902 
5903    Developer Note:
5904    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5905    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5906    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5907    not changed.
5908 
5909 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5910 @*/
5911 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5912 {
5913   PetscFunctionBegin;
5914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5915   if (op > 0) {
5916     PetscValidLogicalCollectiveEnum(mat, op, 2);
5917     PetscValidLogicalCollectiveBool(mat, flg, 3);
5918   }
5919 
5920   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);
5921 
5922   switch (op) {
5923   case MAT_FORCE_DIAGONAL_ENTRIES:
5924     mat->force_diagonals = flg;
5925     PetscFunctionReturn(PETSC_SUCCESS);
5926   case MAT_NO_OFF_PROC_ENTRIES:
5927     mat->nooffprocentries = flg;
5928     PetscFunctionReturn(PETSC_SUCCESS);
5929   case MAT_SUBSET_OFF_PROC_ENTRIES:
5930     mat->assembly_subset = flg;
5931     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5932 #if !defined(PETSC_HAVE_MPIUNI)
5933       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5934 #endif
5935       mat->stash.first_assembly_done = PETSC_FALSE;
5936     }
5937     PetscFunctionReturn(PETSC_SUCCESS);
5938   case MAT_NO_OFF_PROC_ZERO_ROWS:
5939     mat->nooffproczerorows = flg;
5940     PetscFunctionReturn(PETSC_SUCCESS);
5941   case MAT_SPD:
5942     if (flg) {
5943       mat->spd                    = PETSC_BOOL3_TRUE;
5944       mat->symmetric              = PETSC_BOOL3_TRUE;
5945       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5946     } else {
5947       mat->spd = PETSC_BOOL3_FALSE;
5948     }
5949     break;
5950   case MAT_SYMMETRIC:
5951     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5952     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5953 #if !defined(PETSC_USE_COMPLEX)
5954     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5955 #endif
5956     break;
5957   case MAT_HERMITIAN:
5958     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5959     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5960 #if !defined(PETSC_USE_COMPLEX)
5961     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5962 #endif
5963     break;
5964   case MAT_STRUCTURALLY_SYMMETRIC:
5965     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5966     break;
5967   case MAT_SYMMETRY_ETERNAL:
5968     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");
5969     mat->symmetry_eternal = flg;
5970     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5971     break;
5972   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5973     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");
5974     mat->structural_symmetry_eternal = flg;
5975     break;
5976   case MAT_SPD_ETERNAL:
5977     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");
5978     mat->spd_eternal = flg;
5979     if (flg) {
5980       mat->structural_symmetry_eternal = PETSC_TRUE;
5981       mat->symmetry_eternal            = PETSC_TRUE;
5982     }
5983     break;
5984   case MAT_STRUCTURE_ONLY:
5985     mat->structure_only = flg;
5986     break;
5987   case MAT_SORTED_FULL:
5988     mat->sortedfull = flg;
5989     break;
5990   default:
5991     break;
5992   }
5993   PetscTryTypeMethod(mat, setoption, op, flg);
5994   PetscFunctionReturn(PETSC_SUCCESS);
5995 }
5996 
5997 /*@
5998    MatGetOption - Gets a parameter option that has been set for a matrix.
5999 
6000    Logically Collective
6001 
6002    Input Parameters:
6003 +  mat - the matrix
6004 -  option - the option, this only responds to certain options, check the code for which ones
6005 
6006    Output Parameter:
6007 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6008 
6009    Level: intermediate
6010 
6011     Notes:
6012     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6013 
6014     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6015     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6016 
6017 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6018     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6019 @*/
6020 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6021 {
6022   PetscFunctionBegin;
6023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6024   PetscValidType(mat, 1);
6025 
6026   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);
6027   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()");
6028 
6029   switch (op) {
6030   case MAT_NO_OFF_PROC_ENTRIES:
6031     *flg = mat->nooffprocentries;
6032     break;
6033   case MAT_NO_OFF_PROC_ZERO_ROWS:
6034     *flg = mat->nooffproczerorows;
6035     break;
6036   case MAT_SYMMETRIC:
6037     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6038     break;
6039   case MAT_HERMITIAN:
6040     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6041     break;
6042   case MAT_STRUCTURALLY_SYMMETRIC:
6043     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6044     break;
6045   case MAT_SPD:
6046     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6047     break;
6048   case MAT_SYMMETRY_ETERNAL:
6049     *flg = mat->symmetry_eternal;
6050     break;
6051   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6052     *flg = mat->symmetry_eternal;
6053     break;
6054   default:
6055     break;
6056   }
6057   PetscFunctionReturn(PETSC_SUCCESS);
6058 }
6059 
6060 /*@
6061    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6062    this routine retains the old nonzero structure.
6063 
6064    Logically Collective
6065 
6066    Input Parameter:
6067 .  mat - the matrix
6068 
6069    Level: intermediate
6070 
6071    Note:
6072     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.
6073    See the Performance chapter of the users manual for information on preallocating matrices.
6074 
6075 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6076 @*/
6077 PetscErrorCode MatZeroEntries(Mat mat)
6078 {
6079   PetscFunctionBegin;
6080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6081   PetscValidType(mat, 1);
6082   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6083   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");
6084   MatCheckPreallocated(mat, 1);
6085 
6086   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6087   PetscUseTypeMethod(mat, zeroentries);
6088   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6089   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6090   PetscFunctionReturn(PETSC_SUCCESS);
6091 }
6092 
6093 /*@
6094    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6095    of a set of rows and columns of a matrix.
6096 
6097    Collective
6098 
6099    Input Parameters:
6100 +  mat - the matrix
6101 .  numRows - the number of rows/columns to zero
6102 .  rows - the global row indices
6103 .  diag - value put in the diagonal of the eliminated rows
6104 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6105 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6106 
6107    Level: intermediate
6108 
6109    Notes:
6110    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6111 
6112    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6113    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
6114 
6115    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6116    Krylov method to take advantage of the known solution on the zeroed rows.
6117 
6118    For the parallel case, all processes that share the matrix (i.e.,
6119    those in the communicator used for matrix creation) MUST call this
6120    routine, regardless of whether any rows being zeroed are owned by
6121    them.
6122 
6123    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6124 
6125    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6126    list only rows local to itself).
6127 
6128    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6129 
6130 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6131           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6132 @*/
6133 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6134 {
6135   PetscFunctionBegin;
6136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6137   PetscValidType(mat, 1);
6138   if (numRows) PetscValidIntPointer(rows, 3);
6139   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6140   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6141   MatCheckPreallocated(mat, 1);
6142 
6143   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6144   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6145   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6146   PetscFunctionReturn(PETSC_SUCCESS);
6147 }
6148 
6149 /*@
6150    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6151    of a set of rows and columns of a matrix.
6152 
6153    Collective
6154 
6155    Input Parameters:
6156 +  mat - the matrix
6157 .  is - the rows to zero
6158 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6159 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6160 -  b - optional vector of right hand side, that will be adjusted by provided solution
6161 
6162    Level: intermediate
6163 
6164    Note:
6165    See `MatZeroRowsColumns()` for details on how this routine operates.
6166 
6167 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6168           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6169 @*/
6170 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6171 {
6172   PetscInt        numRows;
6173   const PetscInt *rows;
6174 
6175   PetscFunctionBegin;
6176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6177   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6178   PetscValidType(mat, 1);
6179   PetscValidType(is, 2);
6180   PetscCall(ISGetLocalSize(is, &numRows));
6181   PetscCall(ISGetIndices(is, &rows));
6182   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6183   PetscCall(ISRestoreIndices(is, &rows));
6184   PetscFunctionReturn(PETSC_SUCCESS);
6185 }
6186 
6187 /*@
6188    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6189    of a set of rows of a matrix.
6190 
6191    Collective
6192 
6193    Input Parameters:
6194 +  mat - the matrix
6195 .  numRows - the number of rows to zero
6196 .  rows - the global row indices
6197 .  diag - value put in the diagonal of the zeroed rows
6198 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6199 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6200 
6201    Level: intermediate
6202 
6203    Notes:
6204    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6205 
6206    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6207 
6208    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6209    Krylov method to take advantage of the known solution on the zeroed rows.
6210 
6211    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)
6212    from the matrix.
6213 
6214    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6215    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
6216    formats this does not alter the nonzero structure.
6217 
6218    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6219    of the matrix is not changed the values are
6220    merely zeroed.
6221 
6222    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6223    formats can optionally remove the main diagonal entry from the
6224    nonzero structure as well, by passing 0.0 as the final argument).
6225 
6226    For the parallel case, all processes that share the matrix (i.e.,
6227    those in the communicator used for matrix creation) MUST call this
6228    routine, regardless of whether any rows being zeroed are owned by
6229    them.
6230 
6231    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6232    list only rows local to itself).
6233 
6234    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6235    owns that are to be zeroed. This saves a global synchronization in the implementation.
6236 
6237 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6238           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6239 @*/
6240 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6241 {
6242   PetscFunctionBegin;
6243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6244   PetscValidType(mat, 1);
6245   if (numRows) PetscValidIntPointer(rows, 3);
6246   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6247   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6248   MatCheckPreallocated(mat, 1);
6249 
6250   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6251   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6252   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6253   PetscFunctionReturn(PETSC_SUCCESS);
6254 }
6255 
6256 /*@
6257    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6258    of a set of rows of a matrix.
6259 
6260    Collective
6261 
6262    Input Parameters:
6263 +  mat - the matrix
6264 .  is - index set of rows to remove (if `NULL` then no row is removed)
6265 .  diag - value put in all diagonals of eliminated rows
6266 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6267 -  b - optional vector of right hand side, that will be adjusted by provided solution
6268 
6269    Level: intermediate
6270 
6271    Note:
6272    See `MatZeroRows()` for details on how this routine operates.
6273 
6274 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6275           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6276 @*/
6277 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6278 {
6279   PetscInt        numRows = 0;
6280   const PetscInt *rows    = NULL;
6281 
6282   PetscFunctionBegin;
6283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6284   PetscValidType(mat, 1);
6285   if (is) {
6286     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6287     PetscCall(ISGetLocalSize(is, &numRows));
6288     PetscCall(ISGetIndices(is, &rows));
6289   }
6290   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6291   if (is) PetscCall(ISRestoreIndices(is, &rows));
6292   PetscFunctionReturn(PETSC_SUCCESS);
6293 }
6294 
6295 /*@
6296    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6297    of a set of rows of a matrix. These rows must be local to the process.
6298 
6299    Collective
6300 
6301    Input Parameters:
6302 +  mat - the matrix
6303 .  numRows - the number of rows to remove
6304 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6305 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6306 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6307 -  b - optional vector of right hand side, that will be adjusted by provided solution
6308 
6309    Level: intermediate
6310 
6311    Notes:
6312    See `MatZeroRows()` for details on how this routine operates.
6313 
6314    The grid coordinates are across the entire grid, not just the local portion
6315 
6316    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6317    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6318    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6319    `DM_BOUNDARY_PERIODIC` boundary type.
6320 
6321    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
6322    a single value per point) you can skip filling those indices.
6323 
6324    Fortran Note:
6325    `idxm` and `idxn` should be declared as
6326 $     MatStencil idxm(4, m)
6327    and the values inserted using
6328 .vb
6329     idxm(MatStencil_i, 1) = i
6330     idxm(MatStencil_j, 1) = j
6331     idxm(MatStencil_k, 1) = k
6332     idxm(MatStencil_c, 1) = c
6333    etc
6334 .ve
6335 
6336 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6337           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6338 @*/
6339 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6340 {
6341   PetscInt  dim    = mat->stencil.dim;
6342   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6343   PetscInt *dims   = mat->stencil.dims + 1;
6344   PetscInt *starts = mat->stencil.starts;
6345   PetscInt *dxm    = (PetscInt *)rows;
6346   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6347 
6348   PetscFunctionBegin;
6349   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6350   PetscValidType(mat, 1);
6351   if (numRows) PetscValidPointer(rows, 3);
6352 
6353   PetscCall(PetscMalloc1(numRows, &jdxm));
6354   for (i = 0; i < numRows; ++i) {
6355     /* Skip unused dimensions (they are ordered k, j, i, c) */
6356     for (j = 0; j < 3 - sdim; ++j) dxm++;
6357     /* Local index in X dir */
6358     tmp = *dxm++ - starts[0];
6359     /* Loop over remaining dimensions */
6360     for (j = 0; j < dim - 1; ++j) {
6361       /* If nonlocal, set index to be negative */
6362       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6363       /* Update local index */
6364       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6365     }
6366     /* Skip component slot if necessary */
6367     if (mat->stencil.noc) dxm++;
6368     /* Local row number */
6369     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6370   }
6371   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6372   PetscCall(PetscFree(jdxm));
6373   PetscFunctionReturn(PETSC_SUCCESS);
6374 }
6375 
6376 /*@
6377    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6378    of a set of rows and columns of a matrix.
6379 
6380    Collective
6381 
6382    Input Parameters:
6383 +  mat - the matrix
6384 .  numRows - the number of rows/columns to remove
6385 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6386 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6387 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6388 -  b - optional vector of right hand side, that will be adjusted by provided solution
6389 
6390    Level: intermediate
6391 
6392    Notes:
6393    See `MatZeroRowsColumns()` for details on how this routine operates.
6394 
6395    The grid coordinates are across the entire grid, not just the local portion
6396 
6397    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6398    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6399    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6400    `DM_BOUNDARY_PERIODIC` boundary type.
6401 
6402    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
6403    a single value per point) you can skip filling those indices.
6404 
6405    Fortran Note:
6406    `idxm` and `idxn` should be declared as
6407 $     MatStencil idxm(4, m)
6408    and the values inserted using
6409 .vb
6410     idxm(MatStencil_i, 1) = i
6411     idxm(MatStencil_j, 1) = j
6412     idxm(MatStencil_k, 1) = k
6413     idxm(MatStencil_c, 1) = c
6414     etc
6415 .ve
6416 
6417 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6418           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6419 @*/
6420 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6421 {
6422   PetscInt  dim    = mat->stencil.dim;
6423   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6424   PetscInt *dims   = mat->stencil.dims + 1;
6425   PetscInt *starts = mat->stencil.starts;
6426   PetscInt *dxm    = (PetscInt *)rows;
6427   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6428 
6429   PetscFunctionBegin;
6430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6431   PetscValidType(mat, 1);
6432   if (numRows) PetscValidPointer(rows, 3);
6433 
6434   PetscCall(PetscMalloc1(numRows, &jdxm));
6435   for (i = 0; i < numRows; ++i) {
6436     /* Skip unused dimensions (they are ordered k, j, i, c) */
6437     for (j = 0; j < 3 - sdim; ++j) dxm++;
6438     /* Local index in X dir */
6439     tmp = *dxm++ - starts[0];
6440     /* Loop over remaining dimensions */
6441     for (j = 0; j < dim - 1; ++j) {
6442       /* If nonlocal, set index to be negative */
6443       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6444       /* Update local index */
6445       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6446     }
6447     /* Skip component slot if necessary */
6448     if (mat->stencil.noc) dxm++;
6449     /* Local row number */
6450     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6451   }
6452   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6453   PetscCall(PetscFree(jdxm));
6454   PetscFunctionReturn(PETSC_SUCCESS);
6455 }
6456 
6457 /*@C
6458    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6459    of a set of rows of a matrix; using local numbering of rows.
6460 
6461    Collective
6462 
6463    Input Parameters:
6464 +  mat - the matrix
6465 .  numRows - the number of rows to remove
6466 .  rows - the local row indices
6467 .  diag - value put in all diagonals of eliminated rows
6468 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6469 -  b - optional vector of right hand side, that will be adjusted by provided solution
6470 
6471    Level: intermediate
6472 
6473    Notes:
6474    Before calling `MatZeroRowsLocal()`, the user must first set the
6475    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6476 
6477    See `MatZeroRows()` for details on how this routine operates.
6478 
6479 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6480           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6481 @*/
6482 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6483 {
6484   PetscFunctionBegin;
6485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6486   PetscValidType(mat, 1);
6487   if (numRows) PetscValidIntPointer(rows, 3);
6488   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6489   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6490   MatCheckPreallocated(mat, 1);
6491 
6492   if (mat->ops->zerorowslocal) {
6493     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6494   } else {
6495     IS              is, newis;
6496     const PetscInt *newRows;
6497 
6498     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6499     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6500     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6501     PetscCall(ISGetIndices(newis, &newRows));
6502     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6503     PetscCall(ISRestoreIndices(newis, &newRows));
6504     PetscCall(ISDestroy(&newis));
6505     PetscCall(ISDestroy(&is));
6506   }
6507   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6508   PetscFunctionReturn(PETSC_SUCCESS);
6509 }
6510 
6511 /*@
6512    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6513    of a set of rows of a matrix; using local numbering of rows.
6514 
6515    Collective
6516 
6517    Input Parameters:
6518 +  mat - the matrix
6519 .  is - index set of rows to remove
6520 .  diag - value put in all diagonals of eliminated rows
6521 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6522 -  b - optional vector of right hand side, that will be adjusted by provided solution
6523 
6524    Level: intermediate
6525 
6526    Notes:
6527    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6528    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6529 
6530    See `MatZeroRows()` for details on how this routine operates.
6531 
6532 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6533           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6534 @*/
6535 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6536 {
6537   PetscInt        numRows;
6538   const PetscInt *rows;
6539 
6540   PetscFunctionBegin;
6541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6542   PetscValidType(mat, 1);
6543   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6544   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6545   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6546   MatCheckPreallocated(mat, 1);
6547 
6548   PetscCall(ISGetLocalSize(is, &numRows));
6549   PetscCall(ISGetIndices(is, &rows));
6550   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6551   PetscCall(ISRestoreIndices(is, &rows));
6552   PetscFunctionReturn(PETSC_SUCCESS);
6553 }
6554 
6555 /*@
6556    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6557    of a set of rows and columns of a matrix; using local numbering of rows.
6558 
6559    Collective
6560 
6561    Input Parameters:
6562 +  mat - the matrix
6563 .  numRows - the number of rows to remove
6564 .  rows - the global row indices
6565 .  diag - value put in all diagonals of eliminated rows
6566 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6567 -  b - optional vector of right hand side, that will be adjusted by provided solution
6568 
6569    Level: intermediate
6570 
6571    Notes:
6572    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6573    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6574 
6575    See `MatZeroRowsColumns()` for details on how this routine operates.
6576 
6577 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6578           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6579 @*/
6580 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6581 {
6582   IS              is, newis;
6583   const PetscInt *newRows;
6584 
6585   PetscFunctionBegin;
6586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6587   PetscValidType(mat, 1);
6588   if (numRows) PetscValidIntPointer(rows, 3);
6589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6591   MatCheckPreallocated(mat, 1);
6592 
6593   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6594   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6595   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6596   PetscCall(ISGetIndices(newis, &newRows));
6597   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6598   PetscCall(ISRestoreIndices(newis, &newRows));
6599   PetscCall(ISDestroy(&newis));
6600   PetscCall(ISDestroy(&is));
6601   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6602   PetscFunctionReturn(PETSC_SUCCESS);
6603 }
6604 
6605 /*@
6606    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6607    of a set of rows and columns of a matrix; using local numbering of rows.
6608 
6609    Collective
6610 
6611    Input Parameters:
6612 +  mat - the matrix
6613 .  is - index set of rows to remove
6614 .  diag - value put in all diagonals of eliminated rows
6615 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6616 -  b - optional vector of right hand side, that will be adjusted by provided solution
6617 
6618    Level: intermediate
6619 
6620    Notes:
6621    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6622    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6623 
6624    See `MatZeroRowsColumns()` for details on how this routine operates.
6625 
6626 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6627           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6628 @*/
6629 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6630 {
6631   PetscInt        numRows;
6632   const PetscInt *rows;
6633 
6634   PetscFunctionBegin;
6635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6636   PetscValidType(mat, 1);
6637   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6638   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6639   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6640   MatCheckPreallocated(mat, 1);
6641 
6642   PetscCall(ISGetLocalSize(is, &numRows));
6643   PetscCall(ISGetIndices(is, &rows));
6644   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6645   PetscCall(ISRestoreIndices(is, &rows));
6646   PetscFunctionReturn(PETSC_SUCCESS);
6647 }
6648 
6649 /*@C
6650    MatGetSize - Returns the numbers of rows and columns in a matrix.
6651 
6652    Not Collective
6653 
6654    Input Parameter:
6655 .  mat - the matrix
6656 
6657    Output Parameters:
6658 +  m - the number of global rows
6659 -  n - the number of global columns
6660 
6661    Level: beginner
6662 
6663    Note:
6664    Both output parameters can be `NULL` on input.
6665 
6666 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6667 @*/
6668 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6669 {
6670   PetscFunctionBegin;
6671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6672   if (m) *m = mat->rmap->N;
6673   if (n) *n = mat->cmap->N;
6674   PetscFunctionReturn(PETSC_SUCCESS);
6675 }
6676 
6677 /*@C
6678    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6679    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6680 
6681    Not Collective
6682 
6683    Input Parameter:
6684 .  mat - the matrix
6685 
6686    Output Parameters:
6687 +  m - the number of local rows, use `NULL` to not obtain this value
6688 -  n - the number of local columns, use `NULL` to not obtain this value
6689 
6690    Level: beginner
6691 
6692 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6693 @*/
6694 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6695 {
6696   PetscFunctionBegin;
6697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6698   if (m) PetscValidIntPointer(m, 2);
6699   if (n) PetscValidIntPointer(n, 3);
6700   if (m) *m = mat->rmap->n;
6701   if (n) *n = mat->cmap->n;
6702   PetscFunctionReturn(PETSC_SUCCESS);
6703 }
6704 
6705 /*@C
6706    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6707    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6708 
6709    Not Collective, unless matrix has not been allocated, then collective
6710 
6711    Input Parameter:
6712 .  mat - the matrix
6713 
6714    Output Parameters:
6715 +  m - the global index of the first local column, use `NULL` to not obtain this value
6716 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6717 
6718    Level: developer
6719 
6720 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6721 @*/
6722 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6723 {
6724   PetscFunctionBegin;
6725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6726   PetscValidType(mat, 1);
6727   if (m) PetscValidIntPointer(m, 2);
6728   if (n) PetscValidIntPointer(n, 3);
6729   MatCheckPreallocated(mat, 1);
6730   if (m) *m = mat->cmap->rstart;
6731   if (n) *n = mat->cmap->rend;
6732   PetscFunctionReturn(PETSC_SUCCESS);
6733 }
6734 
6735 /*@C
6736    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6737    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
6738    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6739 
6740    Not Collective
6741 
6742    Input Parameter:
6743 .  mat - the matrix
6744 
6745    Output Parameters:
6746 +  m - the global index of the first local row, use `NULL` to not obtain this value
6747 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6748 
6749    Level: beginner
6750 
6751    Note:
6752   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6753   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6754   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6755 
6756 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6757           `PetscLayout`
6758 @*/
6759 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6760 {
6761   PetscFunctionBegin;
6762   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6763   PetscValidType(mat, 1);
6764   if (m) PetscValidIntPointer(m, 2);
6765   if (n) PetscValidIntPointer(n, 3);
6766   MatCheckPreallocated(mat, 1);
6767   if (m) *m = mat->rmap->rstart;
6768   if (n) *n = mat->rmap->rend;
6769   PetscFunctionReturn(PETSC_SUCCESS);
6770 }
6771 
6772 /*@C
6773    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6774    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
6775    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6776 
6777    Not Collective, unless matrix has not been allocated
6778 
6779    Input Parameter:
6780 .  mat - the matrix
6781 
6782    Output Parameter:
6783 .  ranges - start of each processors portion plus one more than the total length at the end
6784 
6785    Level: beginner
6786 
6787 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6788 @*/
6789 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6790 {
6791   PetscFunctionBegin;
6792   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6793   PetscValidType(mat, 1);
6794   MatCheckPreallocated(mat, 1);
6795   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6796   PetscFunctionReturn(PETSC_SUCCESS);
6797 }
6798 
6799 /*@C
6800    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6801    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6802 
6803    Not Collective, unless matrix has not been allocated
6804 
6805    Input Parameter:
6806 .  mat - the matrix
6807 
6808    Output Parameter:
6809 .  ranges - start of each processors portion plus one more then the total length at the end
6810 
6811    Level: beginner
6812 
6813 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6814 @*/
6815 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6816 {
6817   PetscFunctionBegin;
6818   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6819   PetscValidType(mat, 1);
6820   MatCheckPreallocated(mat, 1);
6821   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6822   PetscFunctionReturn(PETSC_SUCCESS);
6823 }
6824 
6825 /*@C
6826    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6827    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6828    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6829 
6830    Not Collective
6831 
6832    Input Parameter:
6833 .  A - matrix
6834 
6835    Output Parameters:
6836 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6837 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6838 
6839    Level: intermediate
6840 
6841 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6842 @*/
6843 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6844 {
6845   PetscErrorCode (*f)(Mat, IS *, IS *);
6846 
6847   PetscFunctionBegin;
6848   MatCheckPreallocated(A, 1);
6849   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6850   if (f) {
6851     PetscCall((*f)(A, rows, cols));
6852   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6853     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6854     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6855   }
6856   PetscFunctionReturn(PETSC_SUCCESS);
6857 }
6858 
6859 /*@C
6860    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6861    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6862    to complete the factorization.
6863 
6864    Collective
6865 
6866    Input Parameters:
6867 +  fact - the factorized matrix obtained with `MatGetFactor()`
6868 .  mat - the matrix
6869 .  row - row permutation
6870 .  col - column permutation
6871 -  info - structure containing
6872 .vb
6873       levels - number of levels of fill.
6874       expected fill - as ratio of original fill.
6875       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6876                 missing diagonal entries)
6877 .ve
6878 
6879    Level: developer
6880 
6881    Notes:
6882    See [Matrix Factorization](sec_matfactor) for additional information.
6883 
6884    Most users should employ the `KSP` interface for linear solvers
6885    instead of working directly with matrix algebra routines such as this.
6886    See, e.g., `KSPCreate()`.
6887 
6888    Uses the definition of level of fill as in Y. Saad, 2003
6889 
6890    Developer Note:
6891    The Fortran interface is not autogenerated as the
6892    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6893 
6894    References:
6895 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6896 
6897 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6898           `MatGetOrdering()`, `MatFactorInfo`
6899 @*/
6900 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6901 {
6902   PetscFunctionBegin;
6903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6904   PetscValidType(mat, 2);
6905   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6906   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6907   PetscValidPointer(info, 5);
6908   PetscValidPointer(fact, 1);
6909   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6910   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6911   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6912   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6913   MatCheckPreallocated(mat, 2);
6914 
6915   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6916   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6917   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6918   PetscFunctionReturn(PETSC_SUCCESS);
6919 }
6920 
6921 /*@C
6922    MatICCFactorSymbolic - Performs symbolic incomplete
6923    Cholesky factorization for a symmetric matrix.  Use
6924    `MatCholeskyFactorNumeric()` to complete the factorization.
6925 
6926    Collective
6927 
6928    Input Parameters:
6929 +  fact - the factorized matrix obtained with `MatGetFactor()`
6930 .  mat - the matrix to be factored
6931 .  perm - row and column permutation
6932 -  info - structure containing
6933 .vb
6934       levels - number of levels of fill.
6935       expected fill - as ratio of original fill.
6936 .ve
6937 
6938    Level: developer
6939 
6940    Notes:
6941    Most users should employ the `KSP` interface for linear solvers
6942    instead of working directly with matrix algebra routines such as this.
6943    See, e.g., `KSPCreate()`.
6944 
6945    This uses the definition of level of fill as in Y. Saad, 2003
6946 
6947    Developer Note:
6948    The Fortran interface is not autogenerated as the
6949    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6950 
6951    References:
6952 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6953 
6954 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6955 @*/
6956 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6957 {
6958   PetscFunctionBegin;
6959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6960   PetscValidType(mat, 2);
6961   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6962   PetscValidPointer(info, 4);
6963   PetscValidPointer(fact, 1);
6964   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6965   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6966   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6967   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6968   MatCheckPreallocated(mat, 2);
6969 
6970   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6971   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6972   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6973   PetscFunctionReturn(PETSC_SUCCESS);
6974 }
6975 
6976 /*@C
6977    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6978    points to an array of valid matrices, they may be reused to store the new
6979    submatrices.
6980 
6981    Collective
6982 
6983    Input Parameters:
6984 +  mat - the matrix
6985 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6986 .  irow - index set of rows to extract
6987 .  icol - index set of columns to extract
6988 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6989 
6990    Output Parameter:
6991 .  submat - the array of submatrices
6992 
6993    Level: advanced
6994 
6995    Notes:
6996    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6997    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6998    to extract a parallel submatrix.
6999 
7000    Some matrix types place restrictions on the row and column
7001    indices, such as that they be sorted or that they be equal to each other.
7002 
7003    The index sets may not have duplicate entries.
7004 
7005    When extracting submatrices from a parallel matrix, each processor can
7006    form a different submatrix by setting the rows and columns of its
7007    individual index sets according to the local submatrix desired.
7008 
7009    When finished using the submatrices, the user should destroy
7010    them with `MatDestroySubMatrices()`.
7011 
7012    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7013    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7014 
7015    This routine creates the matrices in submat; you should NOT create them before
7016    calling it. It also allocates the array of matrix pointers submat.
7017 
7018    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7019    request one row/column in a block, they must request all rows/columns that are in
7020    that block. For example, if the block size is 2 you cannot request just row 0 and
7021    column 0.
7022 
7023    Fortran Note:
7024    The Fortran interface is slightly different from that given below; it
7025    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7026 
7027 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7028 @*/
7029 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7030 {
7031   PetscInt  i;
7032   PetscBool eq;
7033 
7034   PetscFunctionBegin;
7035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7036   PetscValidType(mat, 1);
7037   if (n) {
7038     PetscValidPointer(irow, 3);
7039     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7040     PetscValidPointer(icol, 4);
7041     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7042   }
7043   PetscValidPointer(submat, 6);
7044   if (n && scall == MAT_REUSE_MATRIX) {
7045     PetscValidPointer(*submat, 6);
7046     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7047   }
7048   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7049   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7050   MatCheckPreallocated(mat, 1);
7051   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7052   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7053   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7054   for (i = 0; i < n; i++) {
7055     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7056     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7057     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7058 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7059     if (mat->boundtocpu && mat->bindingpropagates) {
7060       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7061       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7062     }
7063 #endif
7064   }
7065   PetscFunctionReturn(PETSC_SUCCESS);
7066 }
7067 
7068 /*@C
7069    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7070 
7071    Collective
7072 
7073    Input Parameters:
7074 +  mat - the matrix
7075 .  n   - the number of submatrixes to be extracted
7076 .  irow - index set of rows to extract
7077 .  icol - index set of columns to extract
7078 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7079 
7080    Output Parameter:
7081 .  submat - the array of submatrices
7082 
7083    Level: advanced
7084 
7085    Note:
7086    This is used by `PCGASM`
7087 
7088 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7089 @*/
7090 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7091 {
7092   PetscInt  i;
7093   PetscBool eq;
7094 
7095   PetscFunctionBegin;
7096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7097   PetscValidType(mat, 1);
7098   if (n) {
7099     PetscValidPointer(irow, 3);
7100     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7101     PetscValidPointer(icol, 4);
7102     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7103   }
7104   PetscValidPointer(submat, 6);
7105   if (n && scall == MAT_REUSE_MATRIX) {
7106     PetscValidPointer(*submat, 6);
7107     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7108   }
7109   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7110   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7111   MatCheckPreallocated(mat, 1);
7112 
7113   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7114   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7115   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7116   for (i = 0; i < n; i++) {
7117     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7118     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7119   }
7120   PetscFunctionReturn(PETSC_SUCCESS);
7121 }
7122 
7123 /*@C
7124    MatDestroyMatrices - Destroys an array of matrices.
7125 
7126    Collective
7127 
7128    Input Parameters:
7129 +  n - the number of local matrices
7130 -  mat - the matrices (this is a pointer to the array of matrices)
7131 
7132    Level: advanced
7133 
7134     Note:
7135     Frees not only the matrices, but also the array that contains the matrices
7136 
7137     Fortran Note:
7138     This does not free the array.
7139 
7140 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7141 @*/
7142 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7143 {
7144   PetscInt i;
7145 
7146   PetscFunctionBegin;
7147   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7148   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7149   PetscValidPointer(mat, 2);
7150 
7151   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7152 
7153   /* memory is allocated even if n = 0 */
7154   PetscCall(PetscFree(*mat));
7155   PetscFunctionReturn(PETSC_SUCCESS);
7156 }
7157 
7158 /*@C
7159    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7160 
7161    Collective
7162 
7163    Input Parameters:
7164 +  n - the number of local matrices
7165 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7166                        sequence of `MatCreateSubMatrices()`)
7167 
7168    Level: advanced
7169 
7170     Note:
7171     Frees not only the matrices, but also the array that contains the matrices
7172 
7173     Fortran Note:
7174     This does not free the array.
7175 
7176 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7177 @*/
7178 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7179 {
7180   Mat mat0;
7181 
7182   PetscFunctionBegin;
7183   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7184   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7185   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7186   PetscValidPointer(mat, 2);
7187 
7188   mat0 = (*mat)[0];
7189   if (mat0 && mat0->ops->destroysubmatrices) {
7190     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7191   } else {
7192     PetscCall(MatDestroyMatrices(n, mat));
7193   }
7194   PetscFunctionReturn(PETSC_SUCCESS);
7195 }
7196 
7197 /*@C
7198    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7199 
7200    Collective
7201 
7202    Input Parameter:
7203 .  mat - the matrix
7204 
7205    Output Parameter:
7206 .  matstruct - the sequential matrix with the nonzero structure of mat
7207 
7208   Level: developer
7209 
7210 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7211 @*/
7212 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7213 {
7214   PetscFunctionBegin;
7215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7216   PetscValidPointer(matstruct, 2);
7217 
7218   PetscValidType(mat, 1);
7219   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7220   MatCheckPreallocated(mat, 1);
7221 
7222   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7223   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7224   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7225   PetscFunctionReturn(PETSC_SUCCESS);
7226 }
7227 
7228 /*@C
7229    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7230 
7231    Collective
7232 
7233    Input Parameter:
7234 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7235                        sequence of `MatGetSeqNonzeroStructure()`)
7236 
7237    Level: advanced
7238 
7239     Note:
7240     Frees not only the matrices, but also the array that contains the matrices
7241 
7242 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7243 @*/
7244 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7245 {
7246   PetscFunctionBegin;
7247   PetscValidPointer(mat, 1);
7248   PetscCall(MatDestroy(mat));
7249   PetscFunctionReturn(PETSC_SUCCESS);
7250 }
7251 
7252 /*@
7253    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7254    replaces the index sets by larger ones that represent submatrices with
7255    additional overlap.
7256 
7257    Collective
7258 
7259    Input Parameters:
7260 +  mat - the matrix
7261 .  n   - the number of index sets
7262 .  is  - the array of index sets (these index sets will changed during the call)
7263 -  ov  - the additional overlap requested
7264 
7265    Options Database Key:
7266 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7267 
7268    Level: developer
7269 
7270    Note:
7271    The computed overlap preserves the matrix block sizes when the blocks are square.
7272    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7273    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7274 
7275 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7276 @*/
7277 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7278 {
7279   PetscInt i, bs, cbs;
7280 
7281   PetscFunctionBegin;
7282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7283   PetscValidType(mat, 1);
7284   PetscValidLogicalCollectiveInt(mat, n, 2);
7285   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7286   if (n) {
7287     PetscValidPointer(is, 3);
7288     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7289   }
7290   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7291   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7292   MatCheckPreallocated(mat, 1);
7293 
7294   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7295   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7296   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7297   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7298   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7299   if (bs == cbs) {
7300     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7301   }
7302   PetscFunctionReturn(PETSC_SUCCESS);
7303 }
7304 
7305 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7306 
7307 /*@
7308    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7309    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7310    additional overlap.
7311 
7312    Collective
7313 
7314    Input Parameters:
7315 +  mat - the matrix
7316 .  n   - the number of index sets
7317 .  is  - the array of index sets (these index sets will changed during the call)
7318 -  ov  - the additional overlap requested
7319 
7320 `   Options Database Key:
7321 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7322 
7323    Level: developer
7324 
7325 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7326 @*/
7327 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7328 {
7329   PetscInt i;
7330 
7331   PetscFunctionBegin;
7332   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7333   PetscValidType(mat, 1);
7334   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7335   if (n) {
7336     PetscValidPointer(is, 3);
7337     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7338   }
7339   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7340   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7341   MatCheckPreallocated(mat, 1);
7342   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7343   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7344   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7345   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7346   PetscFunctionReturn(PETSC_SUCCESS);
7347 }
7348 
7349 /*@
7350    MatGetBlockSize - Returns the matrix block size.
7351 
7352    Not Collective
7353 
7354    Input Parameter:
7355 .  mat - the matrix
7356 
7357    Output Parameter:
7358 .  bs - block size
7359 
7360    Level: intermediate
7361 
7362    Notes:
7363     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7364 
7365    If the block size has not been set yet this routine returns 1.
7366 
7367 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7368 @*/
7369 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7370 {
7371   PetscFunctionBegin;
7372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7373   PetscValidIntPointer(bs, 2);
7374   *bs = PetscAbs(mat->rmap->bs);
7375   PetscFunctionReturn(PETSC_SUCCESS);
7376 }
7377 
7378 /*@
7379    MatGetBlockSizes - Returns the matrix block row and column sizes.
7380 
7381    Not Collective
7382 
7383    Input Parameter:
7384 .  mat - the matrix
7385 
7386    Output Parameters:
7387 +  rbs - row block size
7388 -  cbs - column block size
7389 
7390    Level: intermediate
7391 
7392    Notes:
7393     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7394     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7395 
7396    If a block size has not been set yet this routine returns 1.
7397 
7398 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7399 @*/
7400 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7401 {
7402   PetscFunctionBegin;
7403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7404   if (rbs) PetscValidIntPointer(rbs, 2);
7405   if (cbs) PetscValidIntPointer(cbs, 3);
7406   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7407   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7408   PetscFunctionReturn(PETSC_SUCCESS);
7409 }
7410 
7411 /*@
7412    MatSetBlockSize - Sets the matrix block size.
7413 
7414    Logically Collective
7415 
7416    Input Parameters:
7417 +  mat - the matrix
7418 -  bs - block size
7419 
7420    Level: intermediate
7421 
7422    Notes:
7423     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7424     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7425 
7426     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7427     is compatible with the matrix local sizes.
7428 
7429 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7430 @*/
7431 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7432 {
7433   PetscFunctionBegin;
7434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7435   PetscValidLogicalCollectiveInt(mat, bs, 2);
7436   PetscCall(MatSetBlockSizes(mat, bs, bs));
7437   PetscFunctionReturn(PETSC_SUCCESS);
7438 }
7439 
7440 typedef struct {
7441   PetscInt         n;
7442   IS              *is;
7443   Mat             *mat;
7444   PetscObjectState nonzerostate;
7445   Mat              C;
7446 } EnvelopeData;
7447 
7448 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7449 {
7450   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7451   PetscCall(PetscFree(edata->is));
7452   PetscCall(PetscFree(edata));
7453   return PETSC_SUCCESS;
7454 }
7455 
7456 /*
7457    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7458          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7459 
7460    Collective
7461 
7462    Input Parameter:
7463 .  mat - the matrix
7464 
7465    Notes:
7466      There can be zeros within the blocks
7467 
7468      The blocks can overlap between processes, including laying on more than two processes
7469 
7470 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7471 */
7472 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7473 {
7474   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7475   PetscInt          *diag, *odiag, sc;
7476   VecScatter         scatter;
7477   PetscScalar       *seqv;
7478   const PetscScalar *parv;
7479   const PetscInt    *ia, *ja;
7480   PetscBool          set, flag, done;
7481   Mat                AA = mat, A;
7482   MPI_Comm           comm;
7483   PetscMPIInt        rank, size, tag;
7484   MPI_Status         status;
7485   PetscContainer     container;
7486   EnvelopeData      *edata;
7487   Vec                seq, par;
7488   IS                 isglobal;
7489 
7490   PetscFunctionBegin;
7491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7492   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7493   if (!set || !flag) {
7494     /* TOO: only needs nonzero structure of transpose */
7495     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7496     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7497   }
7498   PetscCall(MatAIJGetLocalMat(AA, &A));
7499   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7500   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7501 
7502   PetscCall(MatGetLocalSize(mat, &n, NULL));
7503   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7504   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7505   PetscCallMPI(MPI_Comm_size(comm, &size));
7506   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7507 
7508   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7509 
7510   if (rank > 0) {
7511     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7512     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7513   }
7514   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7515   for (i = 0; i < n; i++) {
7516     env = PetscMax(env, ja[ia[i + 1] - 1]);
7517     II  = rstart + i;
7518     if (env == II) {
7519       starts[lblocks]  = tbs;
7520       sizes[lblocks++] = 1 + II - tbs;
7521       tbs              = 1 + II;
7522     }
7523   }
7524   if (rank < size - 1) {
7525     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7526     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7527   }
7528 
7529   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7530   if (!set || !flag) PetscCall(MatDestroy(&AA));
7531   PetscCall(MatDestroy(&A));
7532 
7533   PetscCall(PetscNew(&edata));
7534   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7535   edata->n = lblocks;
7536   /* create IS needed for extracting blocks from the original matrix */
7537   PetscCall(PetscMalloc1(lblocks, &edata->is));
7538   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7539 
7540   /* Create the resulting inverse matrix structure with preallocation information */
7541   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7542   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7543   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7544   PetscCall(MatSetType(edata->C, MATAIJ));
7545 
7546   /* Communicate the start and end of each row, from each block to the correct rank */
7547   /* TODO: Use PetscSF instead of VecScatter */
7548   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7549   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7550   PetscCall(VecGetArrayWrite(seq, &seqv));
7551   for (PetscInt i = 0; i < lblocks; i++) {
7552     for (PetscInt j = 0; j < sizes[i]; j++) {
7553       seqv[cnt]     = starts[i];
7554       seqv[cnt + 1] = starts[i] + sizes[i];
7555       cnt += 2;
7556     }
7557   }
7558   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7559   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7560   sc -= cnt;
7561   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7562   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7563   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7564   PetscCall(ISDestroy(&isglobal));
7565   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7566   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7567   PetscCall(VecScatterDestroy(&scatter));
7568   PetscCall(VecDestroy(&seq));
7569   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7570   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7571   PetscCall(VecGetArrayRead(par, &parv));
7572   cnt = 0;
7573   PetscCall(MatGetSize(mat, NULL, &n));
7574   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7575     PetscInt start, end, d = 0, od = 0;
7576 
7577     start = (PetscInt)PetscRealPart(parv[cnt]);
7578     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7579     cnt += 2;
7580 
7581     if (start < cstart) {
7582       od += cstart - start + n - cend;
7583       d += cend - cstart;
7584     } else if (start < cend) {
7585       od += n - cend;
7586       d += cend - start;
7587     } else od += n - start;
7588     if (end <= cstart) {
7589       od -= cstart - end + n - cend;
7590       d -= cend - cstart;
7591     } else if (end < cend) {
7592       od -= n - cend;
7593       d -= cend - end;
7594     } else od -= n - end;
7595 
7596     odiag[i] = od;
7597     diag[i]  = d;
7598   }
7599   PetscCall(VecRestoreArrayRead(par, &parv));
7600   PetscCall(VecDestroy(&par));
7601   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7602   PetscCall(PetscFree2(diag, odiag));
7603   PetscCall(PetscFree2(sizes, starts));
7604 
7605   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7606   PetscCall(PetscContainerSetPointer(container, edata));
7607   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7608   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7609   PetscCall(PetscObjectDereference((PetscObject)container));
7610   PetscFunctionReturn(PETSC_SUCCESS);
7611 }
7612 
7613 /*@
7614   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7615 
7616   Collective
7617 
7618   Input Parameters:
7619 + A - the matrix
7620 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7621 
7622   Output Parameter:
7623 . C - matrix with inverted block diagonal of `A`
7624 
7625   Level: advanced
7626 
7627   Note:
7628      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7629 
7630 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7631 @*/
7632 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7633 {
7634   PetscContainer   container;
7635   EnvelopeData    *edata;
7636   PetscObjectState nonzerostate;
7637 
7638   PetscFunctionBegin;
7639   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7640   if (!container) {
7641     PetscCall(MatComputeVariableBlockEnvelope(A));
7642     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7643   }
7644   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7645   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7646   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7647   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7648 
7649   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7650   *C = edata->C;
7651 
7652   for (PetscInt i = 0; i < edata->n; i++) {
7653     Mat          D;
7654     PetscScalar *dvalues;
7655 
7656     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7657     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7658     PetscCall(MatSeqDenseInvert(D));
7659     PetscCall(MatDenseGetArray(D, &dvalues));
7660     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7661     PetscCall(MatDestroy(&D));
7662   }
7663   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7664   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7665   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7666   PetscFunctionReturn(PETSC_SUCCESS);
7667 }
7668 
7669 /*@
7670    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7671 
7672    Logically Collective
7673 
7674    Input Parameters:
7675 +  mat - the matrix
7676 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7677 -  bsizes - the block sizes
7678 
7679    Level: intermediate
7680 
7681    Notes:
7682     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7683 
7684     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.
7685 
7686 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7687           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7688 @*/
7689 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7690 {
7691   PetscInt i, ncnt = 0, nlocal;
7692 
7693   PetscFunctionBegin;
7694   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7695   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7696   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7697   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7698   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);
7699   PetscCall(PetscFree(mat->bsizes));
7700   mat->nblocks = nblocks;
7701   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7702   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7703   PetscFunctionReturn(PETSC_SUCCESS);
7704 }
7705 
7706 /*@C
7707    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7708 
7709    Logically Collective; No Fortran Support
7710 
7711    Input Parameter:
7712 .  mat - the matrix
7713 
7714    Output Parameters:
7715 +  nblocks - the number of blocks on this process
7716 -  bsizes - the block sizes
7717 
7718    Level: intermediate
7719 
7720 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7721 @*/
7722 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7723 {
7724   PetscFunctionBegin;
7725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7726   *nblocks = mat->nblocks;
7727   *bsizes  = mat->bsizes;
7728   PetscFunctionReturn(PETSC_SUCCESS);
7729 }
7730 
7731 /*@
7732    MatSetBlockSizes - Sets the matrix block row and column sizes.
7733 
7734    Logically Collective
7735 
7736    Input Parameters:
7737 +  mat - the matrix
7738 .  rbs - row block size
7739 -  cbs - column block size
7740 
7741    Level: intermediate
7742 
7743    Notes:
7744     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7745     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7746     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7747 
7748     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7749     are compatible with the matrix local sizes.
7750 
7751     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7752 
7753 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7754 @*/
7755 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7756 {
7757   PetscFunctionBegin;
7758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7759   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7760   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7761   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7762   if (mat->rmap->refcnt) {
7763     ISLocalToGlobalMapping l2g  = NULL;
7764     PetscLayout            nmap = NULL;
7765 
7766     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7767     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7768     PetscCall(PetscLayoutDestroy(&mat->rmap));
7769     mat->rmap          = nmap;
7770     mat->rmap->mapping = l2g;
7771   }
7772   if (mat->cmap->refcnt) {
7773     ISLocalToGlobalMapping l2g  = NULL;
7774     PetscLayout            nmap = NULL;
7775 
7776     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7777     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7778     PetscCall(PetscLayoutDestroy(&mat->cmap));
7779     mat->cmap          = nmap;
7780     mat->cmap->mapping = l2g;
7781   }
7782   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7783   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7784   PetscFunctionReturn(PETSC_SUCCESS);
7785 }
7786 
7787 /*@
7788    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7789 
7790    Logically Collective
7791 
7792    Input Parameters:
7793 +  mat - the matrix
7794 .  fromRow - matrix from which to copy row block size
7795 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7796 
7797    Level: developer
7798 
7799 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7800 @*/
7801 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7802 {
7803   PetscFunctionBegin;
7804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7805   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7806   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7807   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7808   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7809   PetscFunctionReturn(PETSC_SUCCESS);
7810 }
7811 
7812 /*@
7813    MatResidual - Default routine to calculate the residual r = b - Ax
7814 
7815    Collective
7816 
7817    Input Parameters:
7818 +  mat - the matrix
7819 .  b   - the right-hand-side
7820 -  x   - the approximate solution
7821 
7822    Output Parameter:
7823 .  r - location to store the residual
7824 
7825    Level: developer
7826 
7827 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7828 @*/
7829 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7830 {
7831   PetscFunctionBegin;
7832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7833   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7834   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7835   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7836   PetscValidType(mat, 1);
7837   MatCheckPreallocated(mat, 1);
7838   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7839   if (!mat->ops->residual) {
7840     PetscCall(MatMult(mat, x, r));
7841     PetscCall(VecAYPX(r, -1.0, b));
7842   } else {
7843     PetscUseTypeMethod(mat, residual, b, x, r);
7844   }
7845   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7846   PetscFunctionReturn(PETSC_SUCCESS);
7847 }
7848 
7849 /*MC
7850     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7851 
7852     Synopsis:
7853     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7854 
7855     Not Collective
7856 
7857     Input Parameters:
7858 +   A - the matrix
7859 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7860 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7861 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7862                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7863                  always used.
7864 
7865     Output Parameters:
7866 +   n - number of local rows in the (possibly compressed) matrix
7867 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7868 .   ja - the column indices
7869 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7870            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7871 
7872     Level: developer
7873 
7874     Note:
7875     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7876 
7877 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7878 M*/
7879 
7880 /*MC
7881     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7882 
7883     Synopsis:
7884     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7885 
7886     Not Collective
7887 
7888     Input Parameters:
7889 +   A - the  matrix
7890 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7891 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7892     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7893                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7894                  always used.
7895 .   n - number of local rows in the (possibly compressed) matrix
7896 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7897 .   ja - the column indices
7898 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7899            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7900 
7901     Level: developer
7902 
7903 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7904 M*/
7905 
7906 /*@C
7907     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7908 
7909    Collective
7910 
7911     Input Parameters:
7912 +   mat - the matrix
7913 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7914 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7915 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7916                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7917                  always used.
7918 
7919     Output Parameters:
7920 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7921 .   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
7922 .   ja - the column indices, use `NULL` if not needed
7923 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7924            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7925 
7926     Level: developer
7927 
7928     Notes:
7929     You CANNOT change any of the ia[] or ja[] values.
7930 
7931     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7932 
7933     Fortran Notes:
7934     Use
7935 .vb
7936     PetscInt, pointer :: ia(:),ja(:)
7937     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7938     ! Access the ith and jth entries via ia(i) and ja(j)
7939 .ve
7940    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7941 
7942 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7943 @*/
7944 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7945 {
7946   PetscFunctionBegin;
7947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7948   PetscValidType(mat, 1);
7949   if (n) PetscValidIntPointer(n, 5);
7950   if (ia) PetscValidPointer(ia, 6);
7951   if (ja) PetscValidPointer(ja, 7);
7952   if (done) PetscValidBoolPointer(done, 8);
7953   MatCheckPreallocated(mat, 1);
7954   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7955   else {
7956     if (done) *done = PETSC_TRUE;
7957     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7958     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7959     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7960   }
7961   PetscFunctionReturn(PETSC_SUCCESS);
7962 }
7963 
7964 /*@C
7965     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7966 
7967     Collective
7968 
7969     Input Parameters:
7970 +   mat - the matrix
7971 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7972 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7973                 symmetrized
7974 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7975                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7976                  always used.
7977 .   n - number of columns in the (possibly compressed) matrix
7978 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7979 -   ja - the row indices
7980 
7981     Output Parameter:
7982 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7983 
7984     Level: developer
7985 
7986 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7987 @*/
7988 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7989 {
7990   PetscFunctionBegin;
7991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7992   PetscValidType(mat, 1);
7993   PetscValidIntPointer(n, 5);
7994   if (ia) PetscValidPointer(ia, 6);
7995   if (ja) PetscValidPointer(ja, 7);
7996   PetscValidBoolPointer(done, 8);
7997   MatCheckPreallocated(mat, 1);
7998   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7999   else {
8000     *done = PETSC_TRUE;
8001     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8002   }
8003   PetscFunctionReturn(PETSC_SUCCESS);
8004 }
8005 
8006 /*@C
8007     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8008 
8009     Collective
8010 
8011     Input Parameters:
8012 +   mat - the matrix
8013 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8014 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8015 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8016                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8017                  always used.
8018 .   n - size of (possibly compressed) matrix
8019 .   ia - the row pointers
8020 -   ja - the column indices
8021 
8022     Output Parameter:
8023 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8024 
8025     Level: developer
8026 
8027     Note:
8028     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8029     us of the array after it has been restored. If you pass `NULL`, it will
8030     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8031 
8032     Fortran Note:
8033    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8034 
8035 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8036 @*/
8037 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8038 {
8039   PetscFunctionBegin;
8040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8041   PetscValidType(mat, 1);
8042   if (ia) PetscValidPointer(ia, 6);
8043   if (ja) PetscValidPointer(ja, 7);
8044   if (done) PetscValidBoolPointer(done, 8);
8045   MatCheckPreallocated(mat, 1);
8046 
8047   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8048   else {
8049     if (done) *done = PETSC_TRUE;
8050     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8051     if (n) *n = 0;
8052     if (ia) *ia = NULL;
8053     if (ja) *ja = NULL;
8054   }
8055   PetscFunctionReturn(PETSC_SUCCESS);
8056 }
8057 
8058 /*@C
8059     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8060 
8061     Collective
8062 
8063     Input Parameters:
8064 +   mat - the matrix
8065 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8066 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8067 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8068                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8069                  always used.
8070 
8071     Output Parameters:
8072 +   n - size of (possibly compressed) matrix
8073 .   ia - the column pointers
8074 .   ja - the row indices
8075 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8076 
8077     Level: developer
8078 
8079 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8080 @*/
8081 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8082 {
8083   PetscFunctionBegin;
8084   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8085   PetscValidType(mat, 1);
8086   if (ia) PetscValidPointer(ia, 6);
8087   if (ja) PetscValidPointer(ja, 7);
8088   PetscValidBoolPointer(done, 8);
8089   MatCheckPreallocated(mat, 1);
8090 
8091   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8092   else {
8093     *done = PETSC_TRUE;
8094     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8095     if (n) *n = 0;
8096     if (ia) *ia = NULL;
8097     if (ja) *ja = NULL;
8098   }
8099   PetscFunctionReturn(PETSC_SUCCESS);
8100 }
8101 
8102 /*@C
8103     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8104 
8105     Collective
8106 
8107     Input Parameters:
8108 +   mat - the matrix
8109 .   ncolors - maximum color value
8110 .   n   - number of entries in colorarray
8111 -   colorarray - array indicating color for each column
8112 
8113     Output Parameter:
8114 .   iscoloring - coloring generated using colorarray information
8115 
8116     Level: developer
8117 
8118 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8119 @*/
8120 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8121 {
8122   PetscFunctionBegin;
8123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8124   PetscValidType(mat, 1);
8125   PetscValidIntPointer(colorarray, 4);
8126   PetscValidPointer(iscoloring, 5);
8127   MatCheckPreallocated(mat, 1);
8128 
8129   if (!mat->ops->coloringpatch) {
8130     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8131   } else {
8132     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8133   }
8134   PetscFunctionReturn(PETSC_SUCCESS);
8135 }
8136 
8137 /*@
8138    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8139 
8140    Logically Collective
8141 
8142    Input Parameter:
8143 .  mat - the factored matrix to be reset
8144 
8145    Level: developer
8146 
8147    Notes:
8148    This routine should be used only with factored matrices formed by in-place
8149    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8150    format).  This option can save memory, for example, when solving nonlinear
8151    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8152    ILU(0) preconditioner.
8153 
8154    One can specify in-place ILU(0) factorization by calling
8155 .vb
8156      PCType(pc,PCILU);
8157      PCFactorSeUseInPlace(pc);
8158 .ve
8159    or by using the options -pc_type ilu -pc_factor_in_place
8160 
8161    In-place factorization ILU(0) can also be used as a local
8162    solver for the blocks within the block Jacobi or additive Schwarz
8163    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8164    for details on setting local solver options.
8165 
8166    Most users should employ the `KSP` interface for linear solvers
8167    instead of working directly with matrix algebra routines such as this.
8168    See, e.g., `KSPCreate()`.
8169 
8170 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8171 @*/
8172 PetscErrorCode MatSetUnfactored(Mat mat)
8173 {
8174   PetscFunctionBegin;
8175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8176   PetscValidType(mat, 1);
8177   MatCheckPreallocated(mat, 1);
8178   mat->factortype = MAT_FACTOR_NONE;
8179   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8180   PetscUseTypeMethod(mat, setunfactored);
8181   PetscFunctionReturn(PETSC_SUCCESS);
8182 }
8183 
8184 /*MC
8185     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8186 
8187     Synopsis:
8188     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8189 
8190     Not Collective
8191 
8192     Input Parameter:
8193 .   x - matrix
8194 
8195     Output Parameters:
8196 +   xx_v - the Fortran pointer to the array
8197 -   ierr - error code
8198 
8199     Example of Usage:
8200 .vb
8201       PetscScalar, pointer xx_v(:,:)
8202       ....
8203       call MatDenseGetArrayF90(x,xx_v,ierr)
8204       a = xx_v(3)
8205       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8206 .ve
8207 
8208     Level: advanced
8209 
8210 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8211 M*/
8212 
8213 /*MC
8214     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8215     accessed with `MatDenseGetArrayF90()`.
8216 
8217     Synopsis:
8218     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8219 
8220     Not Collective
8221 
8222     Input Parameters:
8223 +   x - matrix
8224 -   xx_v - the Fortran90 pointer to the array
8225 
8226     Output Parameter:
8227 .   ierr - error code
8228 
8229     Example of Usage:
8230 .vb
8231        PetscScalar, pointer xx_v(:,:)
8232        ....
8233        call MatDenseGetArrayF90(x,xx_v,ierr)
8234        a = xx_v(3)
8235        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8236 .ve
8237 
8238     Level: advanced
8239 
8240 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8241 M*/
8242 
8243 /*MC
8244     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8245 
8246     Synopsis:
8247     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8248 
8249     Not Collective
8250 
8251     Input Parameter:
8252 .   x - matrix
8253 
8254     Output Parameters:
8255 +   xx_v - the Fortran pointer to the array
8256 -   ierr - error code
8257 
8258     Example of Usage:
8259 .vb
8260       PetscScalar, pointer xx_v(:)
8261       ....
8262       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8263       a = xx_v(3)
8264       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8265 .ve
8266 
8267     Level: advanced
8268 
8269 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8270 M*/
8271 
8272 /*MC
8273     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8274     accessed with `MatSeqAIJGetArrayF90()`.
8275 
8276     Synopsis:
8277     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8278 
8279     Not Collective
8280 
8281     Input Parameters:
8282 +   x - matrix
8283 -   xx_v - the Fortran90 pointer to the array
8284 
8285     Output Parameter:
8286 .   ierr - error code
8287 
8288     Example of Usage:
8289 .vb
8290        PetscScalar, pointer xx_v(:)
8291        ....
8292        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8293        a = xx_v(3)
8294        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8295 .ve
8296 
8297     Level: advanced
8298 
8299 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8300 M*/
8301 
8302 /*@
8303     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8304                       as the original matrix.
8305 
8306     Collective
8307 
8308     Input Parameters:
8309 +   mat - the original matrix
8310 .   isrow - parallel `IS` containing the rows this processor should obtain
8311 .   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.
8312 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8313 
8314     Output Parameter:
8315 .   newmat - the new submatrix, of the same type as the original matrix
8316 
8317     Level: advanced
8318 
8319     Notes:
8320     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8321 
8322     Some matrix types place restrictions on the row and column indices, such
8323     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;
8324     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8325 
8326     The index sets may not have duplicate entries.
8327 
8328       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8329    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8330    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8331    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8332    you are finished using it.
8333 
8334     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8335     the input matrix.
8336 
8337     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8338 
8339    Example usage:
8340    Consider the following 8x8 matrix with 34 non-zero values, that is
8341    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8342    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8343    as follows
8344 .vb
8345             1  2  0  |  0  3  0  |  0  4
8346     Proc0   0  5  6  |  7  0  0  |  8  0
8347             9  0 10  | 11  0  0  | 12  0
8348     -------------------------------------
8349            13  0 14  | 15 16 17  |  0  0
8350     Proc1   0 18  0  | 19 20 21  |  0  0
8351             0  0  0  | 22 23  0  | 24  0
8352     -------------------------------------
8353     Proc2  25 26 27  |  0  0 28  | 29  0
8354            30  0  0  | 31 32 33  |  0 34
8355 .ve
8356 
8357     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8358 
8359 .vb
8360             2  0  |  0  3  0  |  0
8361     Proc0   5  6  |  7  0  0  |  8
8362     -------------------------------
8363     Proc1  18  0  | 19 20 21  |  0
8364     -------------------------------
8365     Proc2  26 27  |  0  0 28  | 29
8366             0  0  | 31 32 33  |  0
8367 .ve
8368 
8369 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8370 @*/
8371 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8372 {
8373   PetscMPIInt size;
8374   Mat        *local;
8375   IS          iscoltmp;
8376   PetscBool   flg;
8377 
8378   PetscFunctionBegin;
8379   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8380   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8381   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8382   PetscValidPointer(newmat, 5);
8383   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8384   PetscValidType(mat, 1);
8385   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8386   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8387 
8388   MatCheckPreallocated(mat, 1);
8389   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8390 
8391   if (!iscol || isrow == iscol) {
8392     PetscBool   stride;
8393     PetscMPIInt grabentirematrix = 0, grab;
8394     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8395     if (stride) {
8396       PetscInt first, step, n, rstart, rend;
8397       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8398       if (step == 1) {
8399         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8400         if (rstart == first) {
8401           PetscCall(ISGetLocalSize(isrow, &n));
8402           if (n == rend - rstart) grabentirematrix = 1;
8403         }
8404       }
8405     }
8406     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8407     if (grab) {
8408       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8409       if (cll == MAT_INITIAL_MATRIX) {
8410         *newmat = mat;
8411         PetscCall(PetscObjectReference((PetscObject)mat));
8412       }
8413       PetscFunctionReturn(PETSC_SUCCESS);
8414     }
8415   }
8416 
8417   if (!iscol) {
8418     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8419   } else {
8420     iscoltmp = iscol;
8421   }
8422 
8423   /* if original matrix is on just one processor then use submatrix generated */
8424   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8425     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8426     goto setproperties;
8427   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8428     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8429     *newmat = *local;
8430     PetscCall(PetscFree(local));
8431     goto setproperties;
8432   } else if (!mat->ops->createsubmatrix) {
8433     /* Create a new matrix type that implements the operation using the full matrix */
8434     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8435     switch (cll) {
8436     case MAT_INITIAL_MATRIX:
8437       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8438       break;
8439     case MAT_REUSE_MATRIX:
8440       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8441       break;
8442     default:
8443       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8444     }
8445     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8446     goto setproperties;
8447   }
8448 
8449   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8450   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8451   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8452 
8453 setproperties:
8454   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8455   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8456   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8457   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8458   PetscFunctionReturn(PETSC_SUCCESS);
8459 }
8460 
8461 /*@
8462    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8463 
8464    Not Collective
8465 
8466    Input Parameters:
8467 +  A - the matrix we wish to propagate options from
8468 -  B - the matrix we wish to propagate options to
8469 
8470    Level: beginner
8471 
8472    Note:
8473    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8474 
8475 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8476 @*/
8477 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8478 {
8479   PetscFunctionBegin;
8480   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8481   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8482   B->symmetry_eternal            = A->symmetry_eternal;
8483   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8484   B->symmetric                   = A->symmetric;
8485   B->structurally_symmetric      = A->structurally_symmetric;
8486   B->spd                         = A->spd;
8487   B->hermitian                   = A->hermitian;
8488   PetscFunctionReturn(PETSC_SUCCESS);
8489 }
8490 
8491 /*@
8492    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8493    used during the assembly process to store values that belong to
8494    other processors.
8495 
8496    Not Collective
8497 
8498    Input Parameters:
8499 +  mat   - the matrix
8500 .  size  - the initial size of the stash.
8501 -  bsize - the initial size of the block-stash(if used).
8502 
8503    Options Database Keys:
8504 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8505 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8506 
8507    Level: intermediate
8508 
8509    Notes:
8510      The block-stash is used for values set with `MatSetValuesBlocked()` while
8511      the stash is used for values set with `MatSetValues()`
8512 
8513      Run with the option -info and look for output of the form
8514      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8515      to determine the appropriate value, MM, to use for size and
8516      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8517      to determine the value, BMM to use for bsize
8518 
8519 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8520 @*/
8521 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8522 {
8523   PetscFunctionBegin;
8524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8525   PetscValidType(mat, 1);
8526   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8527   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8528   PetscFunctionReturn(PETSC_SUCCESS);
8529 }
8530 
8531 /*@
8532    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8533      the matrix
8534 
8535    Neighbor-wise Collective
8536 
8537    Input Parameters:
8538 +  mat   - the matrix
8539 .  x - the vector to be multiplied by the interpolation operator
8540 -  y - the vector to be added to the result
8541 
8542    Output Parameter:
8543 .  w - the resulting vector
8544 
8545    Level: intermediate
8546 
8547    Notes:
8548     `w` may be the same vector as `y`.
8549 
8550     This allows one to use either the restriction or interpolation (its transpose)
8551     matrix to do the interpolation
8552 
8553 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8554 @*/
8555 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8556 {
8557   PetscInt M, N, Ny;
8558 
8559   PetscFunctionBegin;
8560   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8561   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8562   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8563   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8564   PetscCall(MatGetSize(A, &M, &N));
8565   PetscCall(VecGetSize(y, &Ny));
8566   if (M == Ny) {
8567     PetscCall(MatMultAdd(A, x, y, w));
8568   } else {
8569     PetscCall(MatMultTransposeAdd(A, x, y, w));
8570   }
8571   PetscFunctionReturn(PETSC_SUCCESS);
8572 }
8573 
8574 /*@
8575    MatInterpolate - y = A*x or A'*x depending on the shape of
8576      the matrix
8577 
8578    Neighbor-wise Collective
8579 
8580    Input Parameters:
8581 +  mat   - the matrix
8582 -  x - the vector to be interpolated
8583 
8584    Output Parameter:
8585 .  y - the resulting vector
8586 
8587    Level: intermediate
8588 
8589    Note:
8590     This allows one to use either the restriction or interpolation (its transpose)
8591     matrix to do the interpolation
8592 
8593 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8594 @*/
8595 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8596 {
8597   PetscInt M, N, Ny;
8598 
8599   PetscFunctionBegin;
8600   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8601   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8602   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8603   PetscCall(MatGetSize(A, &M, &N));
8604   PetscCall(VecGetSize(y, &Ny));
8605   if (M == Ny) {
8606     PetscCall(MatMult(A, x, y));
8607   } else {
8608     PetscCall(MatMultTranspose(A, x, y));
8609   }
8610   PetscFunctionReturn(PETSC_SUCCESS);
8611 }
8612 
8613 /*@
8614    MatRestrict - y = A*x or A'*x
8615 
8616    Neighbor-wise Collective
8617 
8618    Input Parameters:
8619 +  mat   - the matrix
8620 -  x - the vector to be restricted
8621 
8622    Output Parameter:
8623 .  y - the resulting vector
8624 
8625    Level: intermediate
8626 
8627    Note:
8628     This allows one to use either the restriction or interpolation (its transpose)
8629     matrix to do the restriction
8630 
8631 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8632 @*/
8633 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8634 {
8635   PetscInt M, N, Ny;
8636 
8637   PetscFunctionBegin;
8638   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8639   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8640   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8641   PetscCall(MatGetSize(A, &M, &N));
8642   PetscCall(VecGetSize(y, &Ny));
8643   if (M == Ny) {
8644     PetscCall(MatMult(A, x, y));
8645   } else {
8646     PetscCall(MatMultTranspose(A, x, y));
8647   }
8648   PetscFunctionReturn(PETSC_SUCCESS);
8649 }
8650 
8651 /*@
8652    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8653 
8654    Neighbor-wise Collective
8655 
8656    Input Parameters:
8657 +  mat   - the matrix
8658 .  x - the input dense matrix to be multiplied
8659 -  w - the input dense matrix to be added to the result
8660 
8661    Output Parameter:
8662 .  y - the output dense matrix
8663 
8664    Level: intermediate
8665 
8666    Note:
8667     This allows one to use either the restriction or interpolation (its transpose)
8668     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8669     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8670 
8671 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8672 @*/
8673 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8674 {
8675   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8676   PetscBool trans = PETSC_TRUE;
8677   MatReuse  reuse = MAT_INITIAL_MATRIX;
8678 
8679   PetscFunctionBegin;
8680   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8681   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8682   PetscValidType(x, 2);
8683   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8684   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8685   PetscCall(MatGetSize(A, &M, &N));
8686   PetscCall(MatGetSize(x, &Mx, &Nx));
8687   if (N == Mx) trans = PETSC_FALSE;
8688   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);
8689   Mo = trans ? N : M;
8690   if (*y) {
8691     PetscCall(MatGetSize(*y, &My, &Ny));
8692     if (Mo == My && Nx == Ny) {
8693       reuse = MAT_REUSE_MATRIX;
8694     } else {
8695       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);
8696       PetscCall(MatDestroy(y));
8697     }
8698   }
8699 
8700   if (w && *y == w) { /* this is to minimize changes in PCMG */
8701     PetscBool flg;
8702 
8703     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8704     if (w) {
8705       PetscInt My, Ny, Mw, Nw;
8706 
8707       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8708       PetscCall(MatGetSize(*y, &My, &Ny));
8709       PetscCall(MatGetSize(w, &Mw, &Nw));
8710       if (!flg || My != Mw || Ny != Nw) w = NULL;
8711     }
8712     if (!w) {
8713       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8714       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8715       PetscCall(PetscObjectDereference((PetscObject)w));
8716     } else {
8717       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8718     }
8719   }
8720   if (!trans) {
8721     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8722   } else {
8723     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8724   }
8725   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8726   PetscFunctionReturn(PETSC_SUCCESS);
8727 }
8728 
8729 /*@
8730    MatMatInterpolate - Y = A*X or A'*X
8731 
8732    Neighbor-wise Collective
8733 
8734    Input Parameters:
8735 +  mat   - the matrix
8736 -  x - the input dense matrix
8737 
8738    Output Parameter:
8739 .  y - the output dense matrix
8740 
8741    Level: intermediate
8742 
8743    Note:
8744     This allows one to use either the restriction or interpolation (its transpose)
8745     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8746     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8747 
8748 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8749 @*/
8750 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8751 {
8752   PetscFunctionBegin;
8753   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8754   PetscFunctionReturn(PETSC_SUCCESS);
8755 }
8756 
8757 /*@
8758    MatMatRestrict - Y = A*X or A'*X
8759 
8760    Neighbor-wise Collective
8761 
8762    Input Parameters:
8763 +  mat   - the matrix
8764 -  x - the input dense matrix
8765 
8766    Output Parameter:
8767 .  y - the output dense matrix
8768 
8769    Level: intermediate
8770 
8771    Note:
8772     This allows one to use either the restriction or interpolation (its transpose)
8773     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8774     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8775 
8776 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8777 @*/
8778 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8779 {
8780   PetscFunctionBegin;
8781   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8782   PetscFunctionReturn(PETSC_SUCCESS);
8783 }
8784 
8785 /*@
8786    MatGetNullSpace - retrieves the null space of a matrix.
8787 
8788    Logically Collective
8789 
8790    Input Parameters:
8791 +  mat - the matrix
8792 -  nullsp - the null space object
8793 
8794    Level: developer
8795 
8796 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8797 @*/
8798 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8799 {
8800   PetscFunctionBegin;
8801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8802   PetscValidPointer(nullsp, 2);
8803   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8804   PetscFunctionReturn(PETSC_SUCCESS);
8805 }
8806 
8807 /*@
8808    MatSetNullSpace - attaches a null space to a matrix.
8809 
8810    Logically Collective
8811 
8812    Input Parameters:
8813 +  mat - the matrix
8814 -  nullsp - the null space object
8815 
8816    Level: advanced
8817 
8818    Notes:
8819       This null space is used by the `KSP` linear solvers to solve singular systems.
8820 
8821       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`
8822 
8823       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
8824       to zero but the linear system will still be solved in a least squares sense.
8825 
8826       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8827    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).
8828    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
8829    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
8830    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).
8831    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8832 
8833     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8834     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8835     routine also automatically calls `MatSetTransposeNullSpace()`.
8836 
8837     The user should call `MatNullSpaceDestroy()`.
8838 
8839 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8840           `KSPSetPCSide()`
8841 @*/
8842 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8843 {
8844   PetscFunctionBegin;
8845   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8846   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8847   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8848   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8849   mat->nullsp = nullsp;
8850   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8851   PetscFunctionReturn(PETSC_SUCCESS);
8852 }
8853 
8854 /*@
8855    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8856 
8857    Logically Collective
8858 
8859    Input Parameters:
8860 +  mat - the matrix
8861 -  nullsp - the null space object
8862 
8863    Level: developer
8864 
8865 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8866 @*/
8867 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8868 {
8869   PetscFunctionBegin;
8870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8871   PetscValidType(mat, 1);
8872   PetscValidPointer(nullsp, 2);
8873   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8874   PetscFunctionReturn(PETSC_SUCCESS);
8875 }
8876 
8877 /*@
8878    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8879 
8880    Logically Collective
8881 
8882    Input Parameters:
8883 +  mat - the matrix
8884 -  nullsp - the null space object
8885 
8886    Level: advanced
8887 
8888    Notes:
8889    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8890 
8891    See `MatSetNullSpace()`
8892 
8893 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8894 @*/
8895 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8896 {
8897   PetscFunctionBegin;
8898   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8899   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8900   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8901   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8902   mat->transnullsp = nullsp;
8903   PetscFunctionReturn(PETSC_SUCCESS);
8904 }
8905 
8906 /*@
8907    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8908         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8909 
8910    Logically Collective
8911 
8912    Input Parameters:
8913 +  mat - the matrix
8914 -  nullsp - the null space object
8915 
8916    Level: advanced
8917 
8918    Notes:
8919    Overwrites any previous near null space that may have been attached
8920 
8921    You can remove the null space by calling this routine with an nullsp of `NULL`
8922 
8923 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8924 @*/
8925 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8926 {
8927   PetscFunctionBegin;
8928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8929   PetscValidType(mat, 1);
8930   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8931   MatCheckPreallocated(mat, 1);
8932   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8933   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8934   mat->nearnullsp = nullsp;
8935   PetscFunctionReturn(PETSC_SUCCESS);
8936 }
8937 
8938 /*@
8939    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8940 
8941    Not Collective
8942 
8943    Input Parameter:
8944 .  mat - the matrix
8945 
8946    Output Parameter:
8947 .  nullsp - the null space object, `NULL` if not set
8948 
8949    Level: advanced
8950 
8951 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8952 @*/
8953 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8954 {
8955   PetscFunctionBegin;
8956   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8957   PetscValidType(mat, 1);
8958   PetscValidPointer(nullsp, 2);
8959   MatCheckPreallocated(mat, 1);
8960   *nullsp = mat->nearnullsp;
8961   PetscFunctionReturn(PETSC_SUCCESS);
8962 }
8963 
8964 /*@C
8965    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8966 
8967    Collective
8968 
8969    Input Parameters:
8970 +  mat - the matrix
8971 .  row - row/column permutation
8972 -  info - information on desired factorization process
8973 
8974    Level: developer
8975 
8976    Notes:
8977    Probably really in-place only when level of fill is zero, otherwise allocates
8978    new space to store factored matrix and deletes previous memory.
8979 
8980    Most users should employ the `KSP` interface for linear solvers
8981    instead of working directly with matrix algebra routines such as this.
8982    See, e.g., `KSPCreate()`.
8983 
8984    Developer Note:
8985    The Fortran interface is not autogenerated as the
8986    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8987 
8988 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8989 @*/
8990 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8991 {
8992   PetscFunctionBegin;
8993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8994   PetscValidType(mat, 1);
8995   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8996   PetscValidPointer(info, 3);
8997   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8998   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8999   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9000   MatCheckPreallocated(mat, 1);
9001   PetscUseTypeMethod(mat, iccfactor, row, info);
9002   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9003   PetscFunctionReturn(PETSC_SUCCESS);
9004 }
9005 
9006 /*@
9007    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9008          ghosted ones.
9009 
9010    Not Collective
9011 
9012    Input Parameters:
9013 +  mat - the matrix
9014 -  diag - the diagonal values, including ghost ones
9015 
9016    Level: developer
9017 
9018    Notes:
9019     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9020 
9021     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9022 
9023 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9024 @*/
9025 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9026 {
9027   PetscMPIInt size;
9028 
9029   PetscFunctionBegin;
9030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9031   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9032   PetscValidType(mat, 1);
9033 
9034   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9035   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9036   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9037   if (size == 1) {
9038     PetscInt n, m;
9039     PetscCall(VecGetSize(diag, &n));
9040     PetscCall(MatGetSize(mat, NULL, &m));
9041     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9042     PetscCall(MatDiagonalScale(mat, NULL, diag));
9043   } else {
9044     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9045   }
9046   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9047   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9048   PetscFunctionReturn(PETSC_SUCCESS);
9049 }
9050 
9051 /*@
9052    MatGetInertia - Gets the inertia from a factored matrix
9053 
9054    Collective
9055 
9056    Input Parameter:
9057 .  mat - the matrix
9058 
9059    Output Parameters:
9060 +   nneg - number of negative eigenvalues
9061 .   nzero - number of zero eigenvalues
9062 -   npos - number of positive eigenvalues
9063 
9064    Level: advanced
9065 
9066    Note:
9067     Matrix must have been factored by `MatCholeskyFactor()`
9068 
9069 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9070 @*/
9071 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9072 {
9073   PetscFunctionBegin;
9074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9075   PetscValidType(mat, 1);
9076   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9077   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9078   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9079   PetscFunctionReturn(PETSC_SUCCESS);
9080 }
9081 
9082 /*@C
9083    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9084 
9085    Neighbor-wise Collective
9086 
9087    Input Parameters:
9088 +  mat - the factored matrix obtained with `MatGetFactor()`
9089 -  b - the right-hand-side vectors
9090 
9091    Output Parameter:
9092 .  x - the result vectors
9093 
9094    Level: developer
9095 
9096    Note:
9097    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9098    call `MatSolves`(A,x,x).
9099 
9100 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9101 @*/
9102 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9103 {
9104   PetscFunctionBegin;
9105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9106   PetscValidType(mat, 1);
9107   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9108   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9109   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9110 
9111   MatCheckPreallocated(mat, 1);
9112   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9113   PetscUseTypeMethod(mat, solves, b, x);
9114   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9115   PetscFunctionReturn(PETSC_SUCCESS);
9116 }
9117 
9118 /*@
9119    MatIsSymmetric - Test whether a matrix is symmetric
9120 
9121    Collective
9122 
9123    Input Parameters:
9124 +  A - the matrix to test
9125 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9126 
9127    Output Parameter:
9128 .  flg - the result
9129 
9130    Level: intermediate
9131 
9132    Notes:
9133     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9134 
9135     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9136 
9137     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9138     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9139 
9140 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9141           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9142 @*/
9143 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9144 {
9145   PetscFunctionBegin;
9146   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9147   PetscValidBoolPointer(flg, 3);
9148 
9149   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9150   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9151   else {
9152     PetscUseTypeMethod(A, issymmetric, tol, flg);
9153     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9154   }
9155   PetscFunctionReturn(PETSC_SUCCESS);
9156 }
9157 
9158 /*@
9159    MatIsHermitian - Test whether a matrix is Hermitian
9160 
9161    Collective
9162 
9163    Input Parameters:
9164 +  A - the matrix to test
9165 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9166 
9167    Output Parameter:
9168 .  flg - the result
9169 
9170    Level: intermediate
9171 
9172    Notes:
9173     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9174 
9175     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9176 
9177     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9178     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9179 
9180 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9181           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9182 @*/
9183 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9184 {
9185   PetscFunctionBegin;
9186   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9187   PetscValidBoolPointer(flg, 3);
9188 
9189   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9190   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9191   else {
9192     PetscUseTypeMethod(A, ishermitian, tol, flg);
9193     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9194   }
9195   PetscFunctionReturn(PETSC_SUCCESS);
9196 }
9197 
9198 /*@
9199    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9200 
9201    Not Collective
9202 
9203    Input Parameter:
9204 .  A - the matrix to check
9205 
9206    Output Parameters:
9207 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9208 -  flg - the result (only valid if set is `PETSC_TRUE`)
9209 
9210    Level: advanced
9211 
9212    Notes:
9213    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9214    if you want it explicitly checked
9215 
9216     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9217     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9218 
9219 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9220 @*/
9221 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9222 {
9223   PetscFunctionBegin;
9224   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9225   PetscValidBoolPointer(set, 2);
9226   PetscValidBoolPointer(flg, 3);
9227   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9228     *set = PETSC_TRUE;
9229     *flg = PetscBool3ToBool(A->symmetric);
9230   } else {
9231     *set = PETSC_FALSE;
9232   }
9233   PetscFunctionReturn(PETSC_SUCCESS);
9234 }
9235 
9236 /*@
9237    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9238 
9239    Not Collective
9240 
9241    Input Parameter:
9242 .  A - the matrix to check
9243 
9244    Output Parameters:
9245 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9246 -  flg - the result (only valid if set is `PETSC_TRUE`)
9247 
9248    Level: advanced
9249 
9250    Notes:
9251    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9252 
9253    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9254    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9255 
9256 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9257 @*/
9258 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9259 {
9260   PetscFunctionBegin;
9261   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9262   PetscValidBoolPointer(set, 2);
9263   PetscValidBoolPointer(flg, 3);
9264   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9265     *set = PETSC_TRUE;
9266     *flg = PetscBool3ToBool(A->spd);
9267   } else {
9268     *set = PETSC_FALSE;
9269   }
9270   PetscFunctionReturn(PETSC_SUCCESS);
9271 }
9272 
9273 /*@
9274    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9275 
9276    Not Collective
9277 
9278    Input Parameter:
9279 .  A - the matrix to check
9280 
9281    Output Parameters:
9282 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9283 -  flg - the result (only valid if set is `PETSC_TRUE`)
9284 
9285    Level: advanced
9286 
9287    Notes:
9288    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9289    if you want it explicitly checked
9290 
9291    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9292    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9293 
9294 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9295 @*/
9296 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9297 {
9298   PetscFunctionBegin;
9299   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9300   PetscValidBoolPointer(set, 2);
9301   PetscValidBoolPointer(flg, 3);
9302   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9303     *set = PETSC_TRUE;
9304     *flg = PetscBool3ToBool(A->hermitian);
9305   } else {
9306     *set = PETSC_FALSE;
9307   }
9308   PetscFunctionReturn(PETSC_SUCCESS);
9309 }
9310 
9311 /*@
9312    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9313 
9314    Collective
9315 
9316    Input Parameter:
9317 .  A - the matrix to test
9318 
9319    Output Parameter:
9320 .  flg - the result
9321 
9322    Level: intermediate
9323 
9324    Notes:
9325    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9326 
9327    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
9328    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9329 
9330 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9331 @*/
9332 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9333 {
9334   PetscFunctionBegin;
9335   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9336   PetscValidBoolPointer(flg, 2);
9337   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9338     *flg = PetscBool3ToBool(A->structurally_symmetric);
9339   } else {
9340     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9341     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9342   }
9343   PetscFunctionReturn(PETSC_SUCCESS);
9344 }
9345 
9346 /*@
9347    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9348 
9349    Not Collective
9350 
9351    Input Parameter:
9352 .  A - the matrix to check
9353 
9354    Output Parameters:
9355 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9356 -  flg - the result (only valid if set is PETSC_TRUE)
9357 
9358    Level: advanced
9359 
9360    Notes:
9361    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
9362    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9363 
9364    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9365 
9366 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9367 @*/
9368 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9369 {
9370   PetscFunctionBegin;
9371   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9372   PetscValidBoolPointer(set, 2);
9373   PetscValidBoolPointer(flg, 3);
9374   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9375     *set = PETSC_TRUE;
9376     *flg = PetscBool3ToBool(A->structurally_symmetric);
9377   } else {
9378     *set = PETSC_FALSE;
9379   }
9380   PetscFunctionReturn(PETSC_SUCCESS);
9381 }
9382 
9383 /*@
9384    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9385        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9386 
9387     Not Collective
9388 
9389    Input Parameter:
9390 .   mat - the matrix
9391 
9392    Output Parameters:
9393 +   nstash   - the size of the stash
9394 .   reallocs - the number of additional mallocs incurred.
9395 .   bnstash   - the size of the block stash
9396 -   breallocs - the number of additional mallocs incurred.in the block stash
9397 
9398    Level: advanced
9399 
9400 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9401 @*/
9402 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9403 {
9404   PetscFunctionBegin;
9405   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9406   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9407   PetscFunctionReturn(PETSC_SUCCESS);
9408 }
9409 
9410 /*@C
9411    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9412    parallel layout, `PetscLayout` for rows and columns
9413 
9414    Collective
9415 
9416    Input Parameter:
9417 .  mat - the matrix
9418 
9419    Output Parameters:
9420 +   right - (optional) vector that the matrix can be multiplied against
9421 -   left - (optional) vector that the matrix vector product can be stored in
9422 
9423   Level: advanced
9424 
9425    Notes:
9426     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()`.
9427 
9428     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9429 
9430 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9431 @*/
9432 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9433 {
9434   PetscFunctionBegin;
9435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9436   PetscValidType(mat, 1);
9437   if (mat->ops->getvecs) {
9438     PetscUseTypeMethod(mat, getvecs, right, left);
9439   } else {
9440     if (right) {
9441       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9442       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9443       PetscCall(VecSetType(*right, mat->defaultvectype));
9444 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9445       if (mat->boundtocpu && mat->bindingpropagates) {
9446         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9447         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9448       }
9449 #endif
9450     }
9451     if (left) {
9452       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9453       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9454       PetscCall(VecSetType(*left, mat->defaultvectype));
9455 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9456       if (mat->boundtocpu && mat->bindingpropagates) {
9457         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9458         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9459       }
9460 #endif
9461     }
9462   }
9463   PetscFunctionReturn(PETSC_SUCCESS);
9464 }
9465 
9466 /*@C
9467    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9468      with default values.
9469 
9470    Not Collective
9471 
9472    Input Parameter:
9473 .    info - the `MatFactorInfo` data structure
9474 
9475    Level: developer
9476 
9477    Notes:
9478     The solvers are generally used through the `KSP` and `PC` objects, for example
9479           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9480 
9481     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9482 
9483    Developer Note:
9484    The Fortran interface is not autogenerated as the
9485    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9486 
9487 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9488 @*/
9489 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9490 {
9491   PetscFunctionBegin;
9492   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9493   PetscFunctionReturn(PETSC_SUCCESS);
9494 }
9495 
9496 /*@
9497    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9498 
9499    Collective
9500 
9501    Input Parameters:
9502 +  mat - the factored matrix
9503 -  is - the index set defining the Schur indices (0-based)
9504 
9505    Level: advanced
9506 
9507    Notes:
9508     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9509 
9510    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9511 
9512    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9513 
9514 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9515           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9516 @*/
9517 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9518 {
9519   PetscErrorCode (*f)(Mat, IS);
9520 
9521   PetscFunctionBegin;
9522   PetscValidType(mat, 1);
9523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9524   PetscValidType(is, 2);
9525   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9526   PetscCheckSameComm(mat, 1, is, 2);
9527   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9528   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9529   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9530   PetscCall(MatDestroy(&mat->schur));
9531   PetscCall((*f)(mat, is));
9532   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9533   PetscFunctionReturn(PETSC_SUCCESS);
9534 }
9535 
9536 /*@
9537   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9538 
9539    Logically Collective
9540 
9541    Input Parameters:
9542 +  F - the factored matrix obtained by calling `MatGetFactor()`
9543 .  S - location where to return the Schur complement, can be `NULL`
9544 -  status - the status of the Schur complement matrix, can be `NULL`
9545 
9546    Level: advanced
9547 
9548    Notes:
9549    You must call `MatFactorSetSchurIS()` before calling this routine.
9550 
9551    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9552 
9553    The routine provides a copy of the Schur matrix stored within the solver data structures.
9554    The caller must destroy the object when it is no longer needed.
9555    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9556 
9557    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)
9558 
9559    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9560 
9561    Developer Note:
9562     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9563    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9564 
9565 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9566 @*/
9567 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9568 {
9569   PetscFunctionBegin;
9570   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9571   if (S) PetscValidPointer(S, 2);
9572   if (status) PetscValidPointer(status, 3);
9573   if (S) {
9574     PetscErrorCode (*f)(Mat, Mat *);
9575 
9576     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9577     if (f) {
9578       PetscCall((*f)(F, S));
9579     } else {
9580       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9581     }
9582   }
9583   if (status) *status = F->schur_status;
9584   PetscFunctionReturn(PETSC_SUCCESS);
9585 }
9586 
9587 /*@
9588   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9589 
9590    Logically Collective
9591 
9592    Input Parameters:
9593 +  F - the factored matrix obtained by calling `MatGetFactor()`
9594 .  *S - location where to return the Schur complement, can be `NULL`
9595 -  status - the status of the Schur complement matrix, can be `NULL`
9596 
9597    Level: advanced
9598 
9599    Notes:
9600    You must call `MatFactorSetSchurIS()` before calling this routine.
9601 
9602    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9603 
9604    The routine returns a the Schur Complement stored within the data structures of the solver.
9605 
9606    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9607 
9608    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9609 
9610    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9611 
9612    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9613 
9614 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9615 @*/
9616 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9617 {
9618   PetscFunctionBegin;
9619   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9620   if (S) PetscValidPointer(S, 2);
9621   if (status) PetscValidPointer(status, 3);
9622   if (S) *S = F->schur;
9623   if (status) *status = F->schur_status;
9624   PetscFunctionReturn(PETSC_SUCCESS);
9625 }
9626 
9627 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9628 {
9629   Mat S = F->schur;
9630 
9631   PetscFunctionBegin;
9632   switch (F->schur_status) {
9633   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9634   case MAT_FACTOR_SCHUR_INVERTED:
9635     if (S) {
9636       S->ops->solve             = NULL;
9637       S->ops->matsolve          = NULL;
9638       S->ops->solvetranspose    = NULL;
9639       S->ops->matsolvetranspose = NULL;
9640       S->ops->solveadd          = NULL;
9641       S->ops->solvetransposeadd = NULL;
9642       S->factortype             = MAT_FACTOR_NONE;
9643       PetscCall(PetscFree(S->solvertype));
9644     }
9645   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9646     break;
9647   default:
9648     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9649   }
9650   PetscFunctionReturn(PETSC_SUCCESS);
9651 }
9652 
9653 /*@
9654   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9655 
9656    Logically Collective
9657 
9658    Input Parameters:
9659 +  F - the factored matrix obtained by calling `MatGetFactor()`
9660 .  *S - location where the Schur complement is stored
9661 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9662 
9663    Level: advanced
9664 
9665 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9666 @*/
9667 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9668 {
9669   PetscFunctionBegin;
9670   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9671   if (S) {
9672     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9673     *S = NULL;
9674   }
9675   F->schur_status = status;
9676   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9677   PetscFunctionReturn(PETSC_SUCCESS);
9678 }
9679 
9680 /*@
9681   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9682 
9683    Logically Collective
9684 
9685    Input Parameters:
9686 +  F - the factored matrix obtained by calling `MatGetFactor()`
9687 .  rhs - location where the right hand side of the Schur complement system is stored
9688 -  sol - location where the solution of the Schur complement system has to be returned
9689 
9690    Level: advanced
9691 
9692    Notes:
9693    The sizes of the vectors should match the size of the Schur complement
9694 
9695    Must be called after `MatFactorSetSchurIS()`
9696 
9697 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9698 @*/
9699 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9700 {
9701   PetscFunctionBegin;
9702   PetscValidType(F, 1);
9703   PetscValidType(rhs, 2);
9704   PetscValidType(sol, 3);
9705   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9706   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9707   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9708   PetscCheckSameComm(F, 1, rhs, 2);
9709   PetscCheckSameComm(F, 1, sol, 3);
9710   PetscCall(MatFactorFactorizeSchurComplement(F));
9711   switch (F->schur_status) {
9712   case MAT_FACTOR_SCHUR_FACTORED:
9713     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9714     break;
9715   case MAT_FACTOR_SCHUR_INVERTED:
9716     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9717     break;
9718   default:
9719     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9720   }
9721   PetscFunctionReturn(PETSC_SUCCESS);
9722 }
9723 
9724 /*@
9725   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9726 
9727    Logically Collective
9728 
9729    Input Parameters:
9730 +  F - the factored matrix obtained by calling `MatGetFactor()`
9731 .  rhs - location where the right hand side of the Schur complement system is stored
9732 -  sol - location where the solution of the Schur complement system has to be returned
9733 
9734    Level: advanced
9735 
9736    Notes:
9737    The sizes of the vectors should match the size of the Schur complement
9738 
9739    Must be called after `MatFactorSetSchurIS()`
9740 
9741 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9742 @*/
9743 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9744 {
9745   PetscFunctionBegin;
9746   PetscValidType(F, 1);
9747   PetscValidType(rhs, 2);
9748   PetscValidType(sol, 3);
9749   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9750   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9751   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9752   PetscCheckSameComm(F, 1, rhs, 2);
9753   PetscCheckSameComm(F, 1, sol, 3);
9754   PetscCall(MatFactorFactorizeSchurComplement(F));
9755   switch (F->schur_status) {
9756   case MAT_FACTOR_SCHUR_FACTORED:
9757     PetscCall(MatSolve(F->schur, rhs, sol));
9758     break;
9759   case MAT_FACTOR_SCHUR_INVERTED:
9760     PetscCall(MatMult(F->schur, rhs, sol));
9761     break;
9762   default:
9763     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9764   }
9765   PetscFunctionReturn(PETSC_SUCCESS);
9766 }
9767 
9768 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9769 #if PetscDefined(HAVE_CUDA)
9770 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9771 #endif
9772 
9773 /* Schur status updated in the interface */
9774 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9775 {
9776   Mat S = F->schur;
9777 
9778   PetscFunctionBegin;
9779   if (S) {
9780     PetscMPIInt size;
9781     PetscBool   isdense, isdensecuda;
9782 
9783     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9784     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9785     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9786     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9787     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9788     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9789     if (isdense) {
9790       PetscCall(MatSeqDenseInvertFactors_Private(S));
9791     } else if (isdensecuda) {
9792 #if defined(PETSC_HAVE_CUDA)
9793       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9794 #endif
9795     }
9796     // HIP??????????????
9797     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9798   }
9799   PetscFunctionReturn(PETSC_SUCCESS);
9800 }
9801 
9802 /*@
9803   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9804 
9805    Logically Collective
9806 
9807    Input Parameter:
9808 .  F - the factored matrix obtained by calling `MatGetFactor()`
9809 
9810    Level: advanced
9811 
9812    Notes:
9813     Must be called after `MatFactorSetSchurIS()`.
9814 
9815    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9816 
9817 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9818 @*/
9819 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9820 {
9821   PetscFunctionBegin;
9822   PetscValidType(F, 1);
9823   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9824   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9825   PetscCall(MatFactorFactorizeSchurComplement(F));
9826   PetscCall(MatFactorInvertSchurComplement_Private(F));
9827   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9828   PetscFunctionReturn(PETSC_SUCCESS);
9829 }
9830 
9831 /*@
9832   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9833 
9834    Logically Collective
9835 
9836    Input Parameter:
9837 .  F - the factored matrix obtained by calling `MatGetFactor()`
9838 
9839    Level: advanced
9840 
9841    Note:
9842     Must be called after `MatFactorSetSchurIS()`
9843 
9844 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9845 @*/
9846 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9847 {
9848   MatFactorInfo info;
9849 
9850   PetscFunctionBegin;
9851   PetscValidType(F, 1);
9852   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9853   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9854   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9855   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9856   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9857     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9858   } else {
9859     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9860   }
9861   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9862   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9863   PetscFunctionReturn(PETSC_SUCCESS);
9864 }
9865 
9866 /*@
9867    MatPtAP - Creates the matrix product C = P^T * A * P
9868 
9869    Neighbor-wise Collective
9870 
9871    Input Parameters:
9872 +  A - the matrix
9873 .  P - the projection matrix
9874 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9875 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9876           if the result is a dense matrix this is irrelevant
9877 
9878    Output Parameter:
9879 .  C - the product matrix
9880 
9881    Level: intermediate
9882 
9883    Notes:
9884    C will be created and must be destroyed by the user with `MatDestroy()`.
9885 
9886    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9887 
9888    Developer Note:
9889    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9890 
9891 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9892 @*/
9893 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9894 {
9895   PetscFunctionBegin;
9896   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9897   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9898 
9899   if (scall == MAT_INITIAL_MATRIX) {
9900     PetscCall(MatProductCreate(A, P, NULL, C));
9901     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9902     PetscCall(MatProductSetAlgorithm(*C, "default"));
9903     PetscCall(MatProductSetFill(*C, fill));
9904 
9905     (*C)->product->api_user = PETSC_TRUE;
9906     PetscCall(MatProductSetFromOptions(*C));
9907     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);
9908     PetscCall(MatProductSymbolic(*C));
9909   } else { /* scall == MAT_REUSE_MATRIX */
9910     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9911   }
9912 
9913   PetscCall(MatProductNumeric(*C));
9914   (*C)->symmetric = A->symmetric;
9915   (*C)->spd       = A->spd;
9916   PetscFunctionReturn(PETSC_SUCCESS);
9917 }
9918 
9919 /*@
9920    MatRARt - Creates the matrix product C = R * A * R^T
9921 
9922    Neighbor-wise Collective
9923 
9924    Input Parameters:
9925 +  A - the matrix
9926 .  R - the projection matrix
9927 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9928 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9929           if the result is a dense matrix this is irrelevant
9930 
9931    Output Parameter:
9932 .  C - the product matrix
9933 
9934    Level: intermediate
9935 
9936    Notes:
9937    C will be created and must be destroyed by the user with `MatDestroy()`.
9938 
9939    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9940 
9941    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9942    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9943    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9944    We recommend using MatPtAP().
9945 
9946 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9947 @*/
9948 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9949 {
9950   PetscFunctionBegin;
9951   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9952   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9953 
9954   if (scall == MAT_INITIAL_MATRIX) {
9955     PetscCall(MatProductCreate(A, R, NULL, C));
9956     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9957     PetscCall(MatProductSetAlgorithm(*C, "default"));
9958     PetscCall(MatProductSetFill(*C, fill));
9959 
9960     (*C)->product->api_user = PETSC_TRUE;
9961     PetscCall(MatProductSetFromOptions(*C));
9962     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);
9963     PetscCall(MatProductSymbolic(*C));
9964   } else { /* scall == MAT_REUSE_MATRIX */
9965     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9966   }
9967 
9968   PetscCall(MatProductNumeric(*C));
9969   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9970   PetscFunctionReturn(PETSC_SUCCESS);
9971 }
9972 
9973 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9974 {
9975   PetscFunctionBegin;
9976   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9977 
9978   if (scall == MAT_INITIAL_MATRIX) {
9979     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9980     PetscCall(MatProductCreate(A, B, NULL, C));
9981     PetscCall(MatProductSetType(*C, ptype));
9982     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9983     PetscCall(MatProductSetFill(*C, fill));
9984 
9985     (*C)->product->api_user = PETSC_TRUE;
9986     PetscCall(MatProductSetFromOptions(*C));
9987     PetscCall(MatProductSymbolic(*C));
9988   } else { /* scall == MAT_REUSE_MATRIX */
9989     Mat_Product *product = (*C)->product;
9990     PetscBool    isdense;
9991 
9992     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9993     if (isdense && product && product->type != ptype) {
9994       PetscCall(MatProductClear(*C));
9995       product = NULL;
9996     }
9997     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9998     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9999       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10000       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10001       product           = (*C)->product;
10002       product->fill     = fill;
10003       product->api_user = PETSC_TRUE;
10004       product->clear    = PETSC_TRUE;
10005 
10006       PetscCall(MatProductSetType(*C, ptype));
10007       PetscCall(MatProductSetFromOptions(*C));
10008       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);
10009       PetscCall(MatProductSymbolic(*C));
10010     } else { /* user may change input matrices A or B when REUSE */
10011       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10012     }
10013   }
10014   PetscCall(MatProductNumeric(*C));
10015   PetscFunctionReturn(PETSC_SUCCESS);
10016 }
10017 
10018 /*@
10019    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10020 
10021    Neighbor-wise Collective
10022 
10023    Input Parameters:
10024 +  A - the left matrix
10025 .  B - the right matrix
10026 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10027 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10028           if the result is a dense matrix this is irrelevant
10029 
10030    Output Parameter:
10031 .  C - the product matrix
10032 
10033    Notes:
10034    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10035 
10036    `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
10037    call to this function with `MAT_INITIAL_MATRIX`.
10038 
10039    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10040 
10041    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`,
10042    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10043 
10044    Example of Usage:
10045 .vb
10046      MatProductCreate(A,B,NULL,&C);
10047      MatProductSetType(C,MATPRODUCT_AB);
10048      MatProductSymbolic(C);
10049      MatProductNumeric(C); // compute C=A * B
10050      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10051      MatProductNumeric(C);
10052      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10053      MatProductNumeric(C);
10054 .ve
10055 
10056    Level: intermediate
10057 
10058 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10059 @*/
10060 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10061 {
10062   PetscFunctionBegin;
10063   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10064   PetscFunctionReturn(PETSC_SUCCESS);
10065 }
10066 
10067 /*@
10068    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10069 
10070    Neighbor-wise Collective
10071 
10072    Input Parameters:
10073 +  A - the left matrix
10074 .  B - the right matrix
10075 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10076 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10077 
10078    Output Parameter:
10079 .  C - the product matrix
10080 
10081    Level: intermediate
10082 
10083    Notes:
10084    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10085 
10086    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10087 
10088    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10089    actually needed.
10090 
10091    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10092    and for pairs of `MATMPIDENSE` matrices.
10093 
10094    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10095 
10096    Options Database Keys:
10097 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10098               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10099               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10100 
10101 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10102 @*/
10103 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10104 {
10105   PetscFunctionBegin;
10106   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10107   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10108   PetscFunctionReturn(PETSC_SUCCESS);
10109 }
10110 
10111 /*@
10112    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10113 
10114    Neighbor-wise Collective
10115 
10116    Input Parameters:
10117 +  A - the left matrix
10118 .  B - the right matrix
10119 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10120 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10121 
10122    Output Parameter:
10123 .  C - the product matrix
10124 
10125    Level: intermediate
10126 
10127    Notes:
10128    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10129 
10130    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10131 
10132    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10133 
10134    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10135    actually needed.
10136 
10137    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10138    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10139 
10140 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10141 @*/
10142 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10143 {
10144   PetscFunctionBegin;
10145   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10146   PetscFunctionReturn(PETSC_SUCCESS);
10147 }
10148 
10149 /*@
10150    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10151 
10152    Neighbor-wise Collective
10153 
10154    Input Parameters:
10155 +  A - the left matrix
10156 .  B - the middle matrix
10157 .  C - the right matrix
10158 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10159 -  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
10160           if the result is a dense matrix this is irrelevant
10161 
10162    Output Parameter:
10163 .  D - the product matrix
10164 
10165    Level: intermediate
10166 
10167    Notes:
10168    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10169 
10170    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10171 
10172    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10173 
10174    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10175    actually needed.
10176 
10177    If you have many matrices with the same non-zero structure to multiply, you
10178    should use `MAT_REUSE_MATRIX` in all calls but the first
10179 
10180 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10181 @*/
10182 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10183 {
10184   PetscFunctionBegin;
10185   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10186   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10187 
10188   if (scall == MAT_INITIAL_MATRIX) {
10189     PetscCall(MatProductCreate(A, B, C, D));
10190     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10191     PetscCall(MatProductSetAlgorithm(*D, "default"));
10192     PetscCall(MatProductSetFill(*D, fill));
10193 
10194     (*D)->product->api_user = PETSC_TRUE;
10195     PetscCall(MatProductSetFromOptions(*D));
10196     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,
10197                ((PetscObject)C)->type_name);
10198     PetscCall(MatProductSymbolic(*D));
10199   } else { /* user may change input matrices when REUSE */
10200     PetscCall(MatProductReplaceMats(A, B, C, *D));
10201   }
10202   PetscCall(MatProductNumeric(*D));
10203   PetscFunctionReturn(PETSC_SUCCESS);
10204 }
10205 
10206 /*@
10207    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10208 
10209    Collective
10210 
10211    Input Parameters:
10212 +  mat - the matrix
10213 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10214 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10215 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10216 
10217    Output Parameter:
10218 .  matredundant - redundant matrix
10219 
10220    Level: advanced
10221 
10222    Notes:
10223    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10224    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10225 
10226    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10227    calling it.
10228 
10229    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10230 
10231 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10232 @*/
10233 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10234 {
10235   MPI_Comm       comm;
10236   PetscMPIInt    size;
10237   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10238   Mat_Redundant *redund     = NULL;
10239   PetscSubcomm   psubcomm   = NULL;
10240   MPI_Comm       subcomm_in = subcomm;
10241   Mat           *matseq;
10242   IS             isrow, iscol;
10243   PetscBool      newsubcomm = PETSC_FALSE;
10244 
10245   PetscFunctionBegin;
10246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10247   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10248     PetscValidPointer(*matredundant, 5);
10249     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10250   }
10251 
10252   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10253   if (size == 1 || nsubcomm == 1) {
10254     if (reuse == MAT_INITIAL_MATRIX) {
10255       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10256     } else {
10257       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");
10258       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10259     }
10260     PetscFunctionReturn(PETSC_SUCCESS);
10261   }
10262 
10263   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10264   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10265   MatCheckPreallocated(mat, 1);
10266 
10267   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10268   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10269     /* create psubcomm, then get subcomm */
10270     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10271     PetscCallMPI(MPI_Comm_size(comm, &size));
10272     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10273 
10274     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10275     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10276     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10277     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10278     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10279     newsubcomm = PETSC_TRUE;
10280     PetscCall(PetscSubcommDestroy(&psubcomm));
10281   }
10282 
10283   /* get isrow, iscol and a local sequential matrix matseq[0] */
10284   if (reuse == MAT_INITIAL_MATRIX) {
10285     mloc_sub = PETSC_DECIDE;
10286     nloc_sub = PETSC_DECIDE;
10287     if (bs < 1) {
10288       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10289       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10290     } else {
10291       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10292       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10293     }
10294     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10295     rstart = rend - mloc_sub;
10296     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10297     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10298   } else { /* reuse == MAT_REUSE_MATRIX */
10299     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");
10300     /* retrieve subcomm */
10301     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10302     redund = (*matredundant)->redundant;
10303     isrow  = redund->isrow;
10304     iscol  = redund->iscol;
10305     matseq = redund->matseq;
10306   }
10307   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10308 
10309   /* get matredundant over subcomm */
10310   if (reuse == MAT_INITIAL_MATRIX) {
10311     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10312 
10313     /* create a supporting struct and attach it to C for reuse */
10314     PetscCall(PetscNew(&redund));
10315     (*matredundant)->redundant = redund;
10316     redund->isrow              = isrow;
10317     redund->iscol              = iscol;
10318     redund->matseq             = matseq;
10319     if (newsubcomm) {
10320       redund->subcomm = subcomm;
10321     } else {
10322       redund->subcomm = MPI_COMM_NULL;
10323     }
10324   } else {
10325     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10326   }
10327 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10328   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10329     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10330     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10331   }
10332 #endif
10333   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10334   PetscFunctionReturn(PETSC_SUCCESS);
10335 }
10336 
10337 /*@C
10338    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10339    a given `Mat`. Each submatrix can span multiple procs.
10340 
10341    Collective
10342 
10343    Input Parameters:
10344 +  mat - the matrix
10345 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10346 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10347 
10348    Output Parameter:
10349 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10350 
10351   Level: advanced
10352 
10353   Notes:
10354   The submatrix partition across processors is dictated by `subComm` a
10355   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10356   is not restricted to be grouped with consecutive original ranks.
10357 
10358   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10359   map directly to the layout of the original matrix [wrt the local
10360   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10361   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10362   the `subMat`. However the offDiagMat looses some columns - and this is
10363   reconstructed with `MatSetValues()`
10364 
10365   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10366 
10367 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10368 @*/
10369 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10370 {
10371   PetscMPIInt commsize, subCommSize;
10372 
10373   PetscFunctionBegin;
10374   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10375   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10376   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10377 
10378   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");
10379   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10380   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10381   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10382   PetscFunctionReturn(PETSC_SUCCESS);
10383 }
10384 
10385 /*@
10386    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10387 
10388    Not Collective
10389 
10390    Input Parameters:
10391 +  mat - matrix to extract local submatrix from
10392 .  isrow - local row indices for submatrix
10393 -  iscol - local column indices for submatrix
10394 
10395    Output Parameter:
10396 .  submat - the submatrix
10397 
10398    Level: intermediate
10399 
10400    Notes:
10401    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10402 
10403    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10404    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10405 
10406    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10407    `MatSetValuesBlockedLocal()` will also be implemented.
10408 
10409    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10410    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10411 
10412 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10413 @*/
10414 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10415 {
10416   PetscFunctionBegin;
10417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10418   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10419   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10420   PetscCheckSameComm(isrow, 2, iscol, 3);
10421   PetscValidPointer(submat, 4);
10422   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10423 
10424   if (mat->ops->getlocalsubmatrix) {
10425     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10426   } else {
10427     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10428   }
10429   PetscFunctionReturn(PETSC_SUCCESS);
10430 }
10431 
10432 /*@
10433    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10434 
10435    Not Collective
10436 
10437    Input Parameters:
10438 +  mat - matrix to extract local submatrix from
10439 .  isrow - local row indices for submatrix
10440 .  iscol - local column indices for submatrix
10441 -  submat - the submatrix
10442 
10443    Level: intermediate
10444 
10445 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10446 @*/
10447 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10448 {
10449   PetscFunctionBegin;
10450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10451   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10452   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10453   PetscCheckSameComm(isrow, 2, iscol, 3);
10454   PetscValidPointer(submat, 4);
10455   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10456 
10457   if (mat->ops->restorelocalsubmatrix) {
10458     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10459   } else {
10460     PetscCall(MatDestroy(submat));
10461   }
10462   *submat = NULL;
10463   PetscFunctionReturn(PETSC_SUCCESS);
10464 }
10465 
10466 /*@
10467    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10468 
10469    Collective
10470 
10471    Input Parameter:
10472 .  mat - the matrix
10473 
10474    Output Parameter:
10475 .  is - if any rows have zero diagonals this contains the list of them
10476 
10477    Level: developer
10478 
10479 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10480 @*/
10481 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10482 {
10483   PetscFunctionBegin;
10484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10485   PetscValidType(mat, 1);
10486   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10487   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10488 
10489   if (!mat->ops->findzerodiagonals) {
10490     Vec                diag;
10491     const PetscScalar *a;
10492     PetscInt          *rows;
10493     PetscInt           rStart, rEnd, r, nrow = 0;
10494 
10495     PetscCall(MatCreateVecs(mat, &diag, NULL));
10496     PetscCall(MatGetDiagonal(mat, diag));
10497     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10498     PetscCall(VecGetArrayRead(diag, &a));
10499     for (r = 0; r < rEnd - rStart; ++r)
10500       if (a[r] == 0.0) ++nrow;
10501     PetscCall(PetscMalloc1(nrow, &rows));
10502     nrow = 0;
10503     for (r = 0; r < rEnd - rStart; ++r)
10504       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10505     PetscCall(VecRestoreArrayRead(diag, &a));
10506     PetscCall(VecDestroy(&diag));
10507     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10508   } else {
10509     PetscUseTypeMethod(mat, findzerodiagonals, is);
10510   }
10511   PetscFunctionReturn(PETSC_SUCCESS);
10512 }
10513 
10514 /*@
10515    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10516 
10517    Collective
10518 
10519    Input Parameter:
10520 .  mat - the matrix
10521 
10522    Output Parameter:
10523 .  is - contains the list of rows with off block diagonal entries
10524 
10525    Level: developer
10526 
10527 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10528 @*/
10529 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10530 {
10531   PetscFunctionBegin;
10532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10533   PetscValidType(mat, 1);
10534   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10535   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10536 
10537   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10538   PetscFunctionReturn(PETSC_SUCCESS);
10539 }
10540 
10541 /*@C
10542   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10543 
10544   Collective; No Fortran Support
10545 
10546   Input Parameter:
10547 . mat - the matrix
10548 
10549   Output Parameter:
10550 . values - the block inverses in column major order (FORTRAN-like)
10551 
10552   Level: advanced
10553 
10554    Notes:
10555    The size of the blocks is determined by the block size of the matrix.
10556 
10557    The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10558 
10559    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10560 
10561 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10562 @*/
10563 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10564 {
10565   PetscFunctionBegin;
10566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10567   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10568   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10569   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10570   PetscFunctionReturn(PETSC_SUCCESS);
10571 }
10572 
10573 /*@C
10574   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10575 
10576   Collective; No Fortran Support
10577 
10578   Input Parameters:
10579 + mat - the matrix
10580 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10581 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10582 
10583   Output Parameter:
10584 . values - the block inverses in column major order (FORTRAN-like)
10585 
10586   Level: advanced
10587 
10588   Notes:
10589   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10590 
10591   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10592 
10593 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10594 @*/
10595 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10596 {
10597   PetscFunctionBegin;
10598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10599   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10600   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10601   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10602   PetscFunctionReturn(PETSC_SUCCESS);
10603 }
10604 
10605 /*@
10606   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10607 
10608   Collective
10609 
10610   Input Parameters:
10611 + A - the matrix
10612 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10613 
10614   Level: advanced
10615 
10616   Note:
10617   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10618 
10619 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10620 @*/
10621 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10622 {
10623   const PetscScalar *vals;
10624   PetscInt          *dnnz;
10625   PetscInt           m, rstart, rend, bs, i, j;
10626 
10627   PetscFunctionBegin;
10628   PetscCall(MatInvertBlockDiagonal(A, &vals));
10629   PetscCall(MatGetBlockSize(A, &bs));
10630   PetscCall(MatGetLocalSize(A, &m, NULL));
10631   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10632   PetscCall(PetscMalloc1(m / bs, &dnnz));
10633   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10634   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10635   PetscCall(PetscFree(dnnz));
10636   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10637   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10638   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10639   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10640   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10641   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10642   PetscFunctionReturn(PETSC_SUCCESS);
10643 }
10644 
10645 /*@C
10646     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10647     via `MatTransposeColoringCreate()`.
10648 
10649     Collective
10650 
10651     Input Parameter:
10652 .   c - coloring context
10653 
10654     Level: intermediate
10655 
10656 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10657 @*/
10658 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10659 {
10660   MatTransposeColoring matcolor = *c;
10661 
10662   PetscFunctionBegin;
10663   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10664   if (--((PetscObject)matcolor)->refct > 0) {
10665     matcolor = NULL;
10666     PetscFunctionReturn(PETSC_SUCCESS);
10667   }
10668 
10669   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10670   PetscCall(PetscFree(matcolor->rows));
10671   PetscCall(PetscFree(matcolor->den2sp));
10672   PetscCall(PetscFree(matcolor->colorforcol));
10673   PetscCall(PetscFree(matcolor->columns));
10674   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10675   PetscCall(PetscHeaderDestroy(c));
10676   PetscFunctionReturn(PETSC_SUCCESS);
10677 }
10678 
10679 /*@C
10680     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10681     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10682     `MatTransposeColoring` to sparse B.
10683 
10684     Collective
10685 
10686     Input Parameters:
10687 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10688 -   B - sparse matrix
10689 
10690     Output Parameter:
10691 .   Btdense - dense matrix B^T
10692 
10693     Level: developer
10694 
10695     Note:
10696     These are used internally for some implementations of `MatRARt()`
10697 
10698 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10699 @*/
10700 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10701 {
10702   PetscFunctionBegin;
10703   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10704   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10705   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10706 
10707   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10708   PetscFunctionReturn(PETSC_SUCCESS);
10709 }
10710 
10711 /*@C
10712     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10713     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10714     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10715     `Csp` from `Cden`.
10716 
10717     Collective
10718 
10719     Input Parameters:
10720 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10721 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10722 
10723     Output Parameter:
10724 .   Csp - sparse matrix
10725 
10726     Level: developer
10727 
10728     Note:
10729     These are used internally for some implementations of `MatRARt()`
10730 
10731 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10732 @*/
10733 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10734 {
10735   PetscFunctionBegin;
10736   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10737   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10738   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10739 
10740   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10741   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10742   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10743   PetscFunctionReturn(PETSC_SUCCESS);
10744 }
10745 
10746 /*@C
10747    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10748 
10749    Collective
10750 
10751    Input Parameters:
10752 +  mat - the matrix product C
10753 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10754 
10755     Output Parameter:
10756 .   color - the new coloring context
10757 
10758     Level: intermediate
10759 
10760 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10761           `MatTransColoringApplyDenToSp()`
10762 @*/
10763 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10764 {
10765   MatTransposeColoring c;
10766   MPI_Comm             comm;
10767 
10768   PetscFunctionBegin;
10769   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10770   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10771   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10772 
10773   c->ctype = iscoloring->ctype;
10774   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10775 
10776   *color = c;
10777   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10778   PetscFunctionReturn(PETSC_SUCCESS);
10779 }
10780 
10781 /*@
10782       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10783         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10784         same, otherwise it will be larger
10785 
10786      Not Collective
10787 
10788   Input Parameter:
10789 .    A  - the matrix
10790 
10791   Output Parameter:
10792 .    state - the current state
10793 
10794   Level: intermediate
10795 
10796   Notes:
10797     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10798          different matrices
10799 
10800     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10801 
10802     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10803 
10804 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10805 @*/
10806 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10807 {
10808   PetscFunctionBegin;
10809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10810   *state = mat->nonzerostate;
10811   PetscFunctionReturn(PETSC_SUCCESS);
10812 }
10813 
10814 /*@
10815       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10816                  matrices from each processor
10817 
10818     Collective
10819 
10820    Input Parameters:
10821 +    comm - the communicators the parallel matrix will live on
10822 .    seqmat - the input sequential matrices
10823 .    n - number of local columns (or `PETSC_DECIDE`)
10824 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10825 
10826    Output Parameter:
10827 .    mpimat - the parallel matrix generated
10828 
10829     Level: developer
10830 
10831    Note:
10832     The number of columns of the matrix in EACH processor MUST be the same.
10833 
10834 .seealso: [](ch_matrices), `Mat`
10835 @*/
10836 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10837 {
10838   PetscMPIInt size;
10839 
10840   PetscFunctionBegin;
10841   PetscCallMPI(MPI_Comm_size(comm, &size));
10842   if (size == 1) {
10843     if (reuse == MAT_INITIAL_MATRIX) {
10844       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10845     } else {
10846       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10847     }
10848     PetscFunctionReturn(PETSC_SUCCESS);
10849   }
10850 
10851   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");
10852 
10853   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10854   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10855   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10856   PetscFunctionReturn(PETSC_SUCCESS);
10857 }
10858 
10859 /*@
10860      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10861 
10862     Collective
10863 
10864    Input Parameters:
10865 +    A   - the matrix to create subdomains from
10866 -    N   - requested number of subdomains
10867 
10868    Output Parameters:
10869 +    n   - number of subdomains resulting on this MPI process
10870 -    iss - `IS` list with indices of subdomains on this MPI process
10871 
10872     Level: advanced
10873 
10874     Note:
10875     The number of subdomains must be smaller than the communicator size
10876 
10877 .seealso: [](ch_matrices), `Mat`, `IS`
10878 @*/
10879 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10880 {
10881   MPI_Comm    comm, subcomm;
10882   PetscMPIInt size, rank, color;
10883   PetscInt    rstart, rend, k;
10884 
10885   PetscFunctionBegin;
10886   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10887   PetscCallMPI(MPI_Comm_size(comm, &size));
10888   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10889   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);
10890   *n    = 1;
10891   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10892   color = rank / k;
10893   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10894   PetscCall(PetscMalloc1(1, iss));
10895   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10896   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10897   PetscCallMPI(MPI_Comm_free(&subcomm));
10898   PetscFunctionReturn(PETSC_SUCCESS);
10899 }
10900 
10901 /*@
10902    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10903 
10904    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10905    If they are not the same, uses `MatMatMatMult()`.
10906 
10907    Once the coarse grid problem is constructed, correct for interpolation operators
10908    that are not of full rank, which can legitimately happen in the case of non-nested
10909    geometric multigrid.
10910 
10911    Input Parameters:
10912 +  restrct - restriction operator
10913 .  dA - fine grid matrix
10914 .  interpolate - interpolation operator
10915 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10916 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10917 
10918    Output Parameter:
10919 .  A - the Galerkin coarse matrix
10920 
10921    Options Database Key:
10922 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10923 
10924    Level: developer
10925 
10926 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10927 @*/
10928 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10929 {
10930   IS  zerorows;
10931   Vec diag;
10932 
10933   PetscFunctionBegin;
10934   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10935   /* Construct the coarse grid matrix */
10936   if (interpolate == restrct) {
10937     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10938   } else {
10939     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10940   }
10941 
10942   /* If the interpolation matrix is not of full rank, A will have zero rows.
10943      This can legitimately happen in the case of non-nested geometric multigrid.
10944      In that event, we set the rows of the matrix to the rows of the identity,
10945      ignoring the equations (as the RHS will also be zero). */
10946 
10947   PetscCall(MatFindZeroRows(*A, &zerorows));
10948 
10949   if (zerorows != NULL) { /* if there are any zero rows */
10950     PetscCall(MatCreateVecs(*A, &diag, NULL));
10951     PetscCall(MatGetDiagonal(*A, diag));
10952     PetscCall(VecISSet(diag, zerorows, 1.0));
10953     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10954     PetscCall(VecDestroy(&diag));
10955     PetscCall(ISDestroy(&zerorows));
10956   }
10957   PetscFunctionReturn(PETSC_SUCCESS);
10958 }
10959 
10960 /*@C
10961     MatSetOperation - Allows user to set a matrix operation for any matrix type
10962 
10963    Logically Collective
10964 
10965     Input Parameters:
10966 +   mat - the matrix
10967 .   op - the name of the operation
10968 -   f - the function that provides the operation
10969 
10970    Level: developer
10971 
10972     Usage:
10973 .vb
10974   extern PetscErrorCode usermult(Mat, Vec, Vec);
10975 
10976   PetscCall(MatCreateXXX(comm, ..., &A));
10977   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10978 .ve
10979 
10980     Notes:
10981     See the file `include/petscmat.h` for a complete list of matrix
10982     operations, which all have the form MATOP_<OPERATION>, where
10983     <OPERATION> is the name (in all capital letters) of the
10984     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10985 
10986     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10987     sequence as the usual matrix interface routines, since they
10988     are intended to be accessed via the usual matrix interface
10989     routines, e.g.,
10990 .vb
10991   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10992 .ve
10993 
10994     In particular each function MUST return `PETSC_SUCCESS` on success and
10995     nonzero on failure.
10996 
10997     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10998 
10999 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11000 @*/
11001 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11002 {
11003   PetscFunctionBegin;
11004   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11005   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11006   (((void (**)(void))mat->ops)[op]) = f;
11007   PetscFunctionReturn(PETSC_SUCCESS);
11008 }
11009 
11010 /*@C
11011     MatGetOperation - Gets a matrix operation for any matrix type.
11012 
11013     Not Collective
11014 
11015     Input Parameters:
11016 +   mat - the matrix
11017 -   op - the name of the operation
11018 
11019     Output Parameter:
11020 .   f - the function that provides the operation
11021 
11022     Level: developer
11023 
11024     Usage:
11025 .vb
11026       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11027       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11028 .ve
11029 
11030     Notes:
11031     See the file include/petscmat.h for a complete list of matrix
11032     operations, which all have the form MATOP_<OPERATION>, where
11033     <OPERATION> is the name (in all capital letters) of the
11034     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11035 
11036     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11037 
11038 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11039 @*/
11040 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11041 {
11042   PetscFunctionBegin;
11043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11044   *f = (((void (**)(void))mat->ops)[op]);
11045   PetscFunctionReturn(PETSC_SUCCESS);
11046 }
11047 
11048 /*@
11049     MatHasOperation - Determines whether the given matrix supports the particular operation.
11050 
11051    Not Collective
11052 
11053    Input Parameters:
11054 +  mat - the matrix
11055 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11056 
11057    Output Parameter:
11058 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11059 
11060    Level: advanced
11061 
11062    Note:
11063    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11064 
11065 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11066 @*/
11067 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11068 {
11069   PetscFunctionBegin;
11070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11071   PetscValidBoolPointer(has, 3);
11072   if (mat->ops->hasoperation) {
11073     PetscUseTypeMethod(mat, hasoperation, op, has);
11074   } else {
11075     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11076     else {
11077       *has = PETSC_FALSE;
11078       if (op == MATOP_CREATE_SUBMATRIX) {
11079         PetscMPIInt size;
11080 
11081         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11082         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11083       }
11084     }
11085   }
11086   PetscFunctionReturn(PETSC_SUCCESS);
11087 }
11088 
11089 /*@
11090     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11091 
11092    Collective
11093 
11094    Input Parameter:
11095 .  mat - the matrix
11096 
11097    Output Parameter:
11098 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11099 
11100    Level: beginner
11101 
11102 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11103 @*/
11104 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11105 {
11106   PetscFunctionBegin;
11107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11108   PetscValidType(mat, 1);
11109   PetscValidBoolPointer(cong, 2);
11110   if (!mat->rmap || !mat->cmap) {
11111     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11112     PetscFunctionReturn(PETSC_SUCCESS);
11113   }
11114   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11115     PetscCall(PetscLayoutSetUp(mat->rmap));
11116     PetscCall(PetscLayoutSetUp(mat->cmap));
11117     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11118     if (*cong) mat->congruentlayouts = 1;
11119     else mat->congruentlayouts = 0;
11120   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11121   PetscFunctionReturn(PETSC_SUCCESS);
11122 }
11123 
11124 PetscErrorCode MatSetInf(Mat A)
11125 {
11126   PetscFunctionBegin;
11127   PetscUseTypeMethod(A, setinf);
11128   PetscFunctionReturn(PETSC_SUCCESS);
11129 }
11130 
11131 /*@C
11132    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
11133    and possibly removes small values from the graph structure.
11134 
11135    Collective
11136 
11137    Input Parameters:
11138 +  A - the matrix
11139 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11140 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11141 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11142 
11143    Output Parameter:
11144 .  graph - the resulting graph
11145 
11146    Level: advanced
11147 
11148 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11149 @*/
11150 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11151 {
11152   PetscFunctionBegin;
11153   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11154   PetscValidType(A, 1);
11155   PetscValidLogicalCollectiveBool(A, scale, 3);
11156   PetscValidPointer(graph, 5);
11157   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11158   PetscFunctionReturn(PETSC_SUCCESS);
11159 }
11160 
11161 /*@
11162   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11163   meaning the same memory is used for the matrix, and no new memory is allocated.
11164 
11165   Collective
11166 
11167   Input Parameter:
11168 . A - the matrix
11169 
11170   Level: intermediate
11171 
11172   Developer Note:
11173   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11174   of the arrays in the data structure are unneeded.
11175 
11176 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11177 @*/
11178 PetscErrorCode MatEliminateZeros(Mat A)
11179 {
11180   PetscFunctionBegin;
11181   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11182   PetscUseTypeMethod(A, eliminatezeros);
11183   PetscFunctionReturn(PETSC_SUCCESS);
11184 }
11185