xref: /petsc/src/mat/interface/matrix.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_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. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
52                   for sparse matrices that already have locations it fills the locations with random numbers
53 
54    Logically Collective
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
59           it will create one internally.
60 
61    Output Parameter:
62 .  x  - the matrix
63 
64    Example of Usage:
65 .vb
66      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
67      MatSetRandom(x,rctx);
68      PetscRandomDestroy(rctx);
69 .ve
70 
71    Level: intermediate
72 
73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
74 @*/
75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
76 {
77   PetscRandom randObj = NULL;
78 
79   PetscFunctionBegin;
80   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
81   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
82   PetscValidType(x, 1);
83   MatCheckPreallocated(x, 1);
84 
85   if (!rctx) {
86     MPI_Comm comm;
87     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
88     PetscCall(PetscRandomCreate(comm, &randObj));
89     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
90     PetscCall(PetscRandomSetFromOptions(randObj));
91     rctx = randObj;
92   }
93   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
94   PetscUseTypeMethod(x, setrandom, rctx);
95   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
96 
97   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
98   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
99   PetscCall(PetscRandomDestroy(&randObj));
100   PetscFunctionReturn(PETSC_SUCCESS);
101 }
102 
103 /*@
104    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
105 
106    Logically Collective
107 
108    Input Parameter:
109 .  mat - the factored matrix
110 
111    Output Parameters:
112 +  pivot - the pivot value computed
113 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
114          the share the matrix
115 
116    Level: advanced
117 
118    Notes:
119     This routine does not work for factorizations done with external packages.
120 
121     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
122 
123     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
124 
125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
126           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
127 @*/
128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
129 {
130   PetscFunctionBegin;
131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
132   PetscValidRealPointer(pivot, 2);
133   PetscValidIntPointer(row, 3);
134   *pivot = mat->factorerror_zeropivot_value;
135   *row   = mat->factorerror_zeropivot_row;
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*@
140    MatFactorGetError - gets the error code from a factorization
141 
142    Logically Collective
143 
144    Input Parameters:
145 .  mat - the factored matrix
146 
147    Output Parameter:
148 .  err  - the error code
149 
150    Level: advanced
151 
152    Note:
153     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
154 
155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
156           `MatFactorError`
157 @*/
158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
159 {
160   PetscFunctionBegin;
161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
162   PetscValidPointer(err, 2);
163   *err = mat->factorerrortype;
164   PetscFunctionReturn(PETSC_SUCCESS);
165 }
166 
167 /*@
168    MatFactorClearError - clears the error code in a factorization
169 
170    Logically Collective
171 
172    Input Parameter:
173 .  mat - the factored matrix
174 
175    Level: developer
176 
177    Note:
178     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
179 
180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
181           `MatGetErrorCode()`, `MatFactorError`
182 @*/
183 PetscErrorCode MatFactorClearError(Mat mat)
184 {
185   PetscFunctionBegin;
186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
187   mat->factorerrortype             = MAT_FACTOR_NOERROR;
188   mat->factorerror_zeropivot_value = 0.0;
189   mat->factorerror_zeropivot_row   = 0;
190   PetscFunctionReturn(PETSC_SUCCESS);
191 }
192 
193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
194 {
195   Vec                r, l;
196   const PetscScalar *al;
197   PetscInt           i, nz, gnz, N, n;
198 
199   PetscFunctionBegin;
200   PetscCall(MatCreateVecs(mat, &r, &l));
201   if (!cols) { /* nonzero rows */
202     PetscCall(MatGetSize(mat, &N, NULL));
203     PetscCall(MatGetLocalSize(mat, &n, NULL));
204     PetscCall(VecSet(l, 0.0));
205     PetscCall(VecSetRandom(r, NULL));
206     PetscCall(MatMult(mat, r, l));
207     PetscCall(VecGetArrayRead(l, &al));
208   } else { /* nonzero columns */
209     PetscCall(MatGetSize(mat, NULL, &N));
210     PetscCall(MatGetLocalSize(mat, NULL, &n));
211     PetscCall(VecSet(r, 0.0));
212     PetscCall(VecSetRandom(l, NULL));
213     PetscCall(MatMultTranspose(mat, l, r));
214     PetscCall(VecGetArrayRead(r, &al));
215   }
216   if (tol <= 0.0) {
217     for (i = 0, nz = 0; i < n; i++)
218       if (al[i] != 0.0) nz++;
219   } else {
220     for (i = 0, nz = 0; i < n; i++)
221       if (PetscAbsScalar(al[i]) > tol) nz++;
222   }
223   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
224   if (gnz != N) {
225     PetscInt *nzr;
226     PetscCall(PetscMalloc1(nz, &nzr));
227     if (nz) {
228       if (tol < 0) {
229         for (i = 0, nz = 0; i < n; i++)
230           if (al[i] != 0.0) nzr[nz++] = i;
231       } else {
232         for (i = 0, nz = 0; i < n; i++)
233           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
234       }
235     }
236     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
237   } else *nonzero = NULL;
238   if (!cols) { /* nonzero rows */
239     PetscCall(VecRestoreArrayRead(l, &al));
240   } else {
241     PetscCall(VecRestoreArrayRead(r, &al));
242   }
243   PetscCall(VecDestroy(&l));
244   PetscCall(VecDestroy(&r));
245   PetscFunctionReturn(PETSC_SUCCESS);
246 }
247 
248 /*@
249       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
250 
251   Input Parameter:
252 .    A  - the matrix
253 
254   Output Parameter:
255 .    keptrows - the rows that are not completely zero
256 
257   Note:
258     keptrows is set to NULL if all rows are nonzero.
259 
260   Level: intermediate
261 
262 .seealso: `Mat`, `MatFindZeroRows()`
263  @*/
264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
265 {
266   PetscFunctionBegin;
267   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
268   PetscValidType(mat, 1);
269   PetscValidPointer(keptrows, 2);
270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
272   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
273   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
274   PetscFunctionReturn(PETSC_SUCCESS);
275 }
276 
277 /*@
278       MatFindZeroRows - Locate all rows that are completely zero in the matrix
279 
280   Input Parameter:
281 .    A  - the matrix
282 
283   Output Parameter:
284 .    zerorows - the rows that are completely zero
285 
286   Note:
287     zerorows is set to NULL if no rows are zero.
288 
289   Level: intermediate
290 
291 .seealso: `Mat`, `MatFindNonzeroRows()`
292  @*/
293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
294 {
295   IS       keptrows;
296   PetscInt m, n;
297 
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
300   PetscValidType(mat, 1);
301   PetscValidPointer(zerorows, 2);
302   PetscCall(MatFindNonzeroRows(mat, &keptrows));
303   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
304      In keeping with this convention, we set zerorows to NULL if there are no zero
305      rows. */
306   if (keptrows == NULL) {
307     *zerorows = NULL;
308   } else {
309     PetscCall(MatGetOwnershipRange(mat, &m, &n));
310     PetscCall(ISComplement(keptrows, m, n, zerorows));
311     PetscCall(ISDestroy(&keptrows));
312   }
313   PetscFunctionReturn(PETSC_SUCCESS);
314 }
315 
316 /*@
317    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
318 
319    Not Collective
320 
321    Input Parameters:
322 .   A - the matrix
323 
324    Output Parameters:
325 .   a - the diagonal part (which is a SEQUENTIAL matrix)
326 
327    Notes:
328    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
329 
330    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
331 
332    Level: advanced
333 
334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
335 @*/
336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
337 {
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
340   PetscValidType(A, 1);
341   PetscValidPointer(a, 2);
342   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
343   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
344   else {
345     PetscMPIInt size;
346 
347     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
348     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
349     *a = A;
350   }
351   PetscFunctionReturn(PETSC_SUCCESS);
352 }
353 
354 /*@
355    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
356 
357    Collective
358 
359    Input Parameters:
360 .  mat - the matrix
361 
362    Output Parameter:
363 .   trace - the sum of the diagonal entries
364 
365    Level: advanced
366 
367 .seealso: `Mat`
368 @*/
369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
370 {
371   Vec diag;
372 
373   PetscFunctionBegin;
374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
375   PetscValidScalarPointer(trace, 2);
376   PetscCall(MatCreateVecs(mat, &diag, NULL));
377   PetscCall(MatGetDiagonal(mat, diag));
378   PetscCall(VecSum(diag, trace));
379   PetscCall(VecDestroy(&diag));
380   PetscFunctionReturn(PETSC_SUCCESS);
381 }
382 
383 /*@
384    MatRealPart - Zeros out the imaginary part of the matrix
385 
386    Logically Collective
387 
388    Input Parameters:
389 .  mat - the matrix
390 
391    Level: advanced
392 
393 .seealso: `MatImaginaryPart()`
394 @*/
395 PetscErrorCode MatRealPart(Mat mat)
396 {
397   PetscFunctionBegin;
398   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
399   PetscValidType(mat, 1);
400   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
401   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
402   MatCheckPreallocated(mat, 1);
403   PetscUseTypeMethod(mat, realpart);
404   PetscFunctionReturn(PETSC_SUCCESS);
405 }
406 
407 /*@C
408    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
409 
410    Collective
411 
412    Input Parameter:
413 .  mat - the matrix
414 
415    Output Parameters:
416 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
417 -   ghosts - the global indices of the ghost points
418 
419    Note:
420     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
421 
422    Level: advanced
423 
424 .seealso: `Mat`, `VecCreateGhost()`
425 @*/
426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
427 {
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
430   PetscValidType(mat, 1);
431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
433   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
434   else {
435     if (nghosts) *nghosts = 0;
436     if (ghosts) *ghosts = NULL;
437   }
438   PetscFunctionReturn(PETSC_SUCCESS);
439 }
440 
441 /*@
442    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
443 
444    Logically Collective
445 
446    Input Parameters:
447 .  mat - the matrix
448 
449    Level: advanced
450 
451 .seealso: `MatRealPart()`
452 @*/
453 PetscErrorCode MatImaginaryPart(Mat mat)
454 {
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
457   PetscValidType(mat, 1);
458   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
459   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
460   MatCheckPreallocated(mat, 1);
461   PetscUseTypeMethod(mat, imaginarypart);
462   PetscFunctionReturn(PETSC_SUCCESS);
463 }
464 
465 /*@
466    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
467 
468    Not Collective
469 
470    Input Parameter:
471 .  mat - the matrix
472 
473    Output Parameters:
474 +  missing - is any diagonal missing
475 -  dd - first diagonal entry that is missing (optional) on this process
476 
477    Level: advanced
478 
479 .seealso: `Mat`
480 @*/
481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
482 {
483   PetscFunctionBegin;
484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
485   PetscValidType(mat, 1);
486   PetscValidBoolPointer(missing, 2);
487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
489   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
490   PetscFunctionReturn(PETSC_SUCCESS);
491 }
492 
493 /*@C
494    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
495    for each row that you get to ensure that your application does
496    not bleed memory.
497 
498    Not Collective
499 
500    Input Parameters:
501 +  mat - the matrix
502 -  row - the row to get
503 
504    Output Parameters:
505 +  ncols -  if not NULL, the number of nonzeros in the row
506 .  cols - if not NULL, the column numbers
507 -  vals - if not NULL, the values
508 
509    Notes:
510    This routine is provided for people who need to have direct access
511    to the structure of a matrix.  We hope that we provide enough
512    high-level matrix routines that few users will need it.
513 
514    `MatGetRow()` always returns 0-based column indices, regardless of
515    whether the internal representation is 0-based (default) or 1-based.
516 
517    For better efficiency, set cols and/or vals to NULL if you do
518    not wish to extract these quantities.
519 
520    The user can only examine the values extracted with `MatGetRow()`;
521    the values cannot be altered.  To change the matrix entries, one
522    must use `MatSetValues()`.
523 
524    You can only have one call to `MatGetRow()` outstanding for a particular
525    matrix at a time, per processor. `MatGetRow()` can only obtain rows
526    associated with the given processor, it cannot get rows from the
527    other processors; for that we suggest using `MatCreateSubMatrices()`, then
528    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
529    is in the global number of rows.
530 
531    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
532 
533    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
534 
535    Fortran Note:
536    The calling sequence from Fortran is
537 .vb
538    MatGetRow(matrix,row,ncols,cols,values,ierr)
539          Mat     matrix (input)
540          integer row    (input)
541          integer ncols  (output)
542          integer cols(maxcols) (output)
543          double precision (or double complex) values(maxcols) output
544 .ve
545    where maxcols >= maximum nonzeros in any row of the matrix.
546 
547    Caution:
548    Do not try to change the contents of the output arrays (cols and vals).
549    In some cases, this may corrupt the matrix.
550 
551    Level: advanced
552 
553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
554 @*/
555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
556 {
557   PetscInt incols;
558 
559   PetscFunctionBegin;
560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
561   PetscValidType(mat, 1);
562   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
563   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
564   MatCheckPreallocated(mat, 1);
565   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);
566   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
567   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
568   if (ncols) *ncols = incols;
569   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
570   PetscFunctionReturn(PETSC_SUCCESS);
571 }
572 
573 /*@
574    MatConjugate - replaces the matrix values with their complex conjugates
575 
576    Logically Collective
577 
578    Input Parameters:
579 .  mat - the matrix
580 
581    Level: advanced
582 
583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
584 @*/
585 PetscErrorCode MatConjugate(Mat mat)
586 {
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
590   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
591     PetscUseTypeMethod(mat, conjugate);
592     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
593   }
594   PetscFunctionReturn(PETSC_SUCCESS);
595 }
596 
597 /*@C
598    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
599 
600    Not Collective
601 
602    Input Parameters:
603 +  mat - the matrix
604 .  row - the row to get
605 .  ncols, cols - the number of nonzeros and their columns
606 -  vals - if nonzero the column values
607 
608    Notes:
609    This routine should be called after you have finished examining the entries.
610 
611    This routine zeros out ncols, cols, and vals. This is to prevent accidental
612    us of the array after it has been restored. If you pass NULL, it will
613    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
614 
615    Fortran Notes:
616    The calling sequence from Fortran is
617 .vb
618    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
619       Mat     matrix (input)
620       integer row    (input)
621       integer ncols  (output)
622       integer cols(maxcols) (output)
623       double precision (or double complex) values(maxcols) output
624 .ve
625    Where maxcols >= maximum nonzeros in any row of the matrix.
626 
627    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
628    before another call to `MatGetRow()` can be made.
629 
630    Level: advanced
631 
632 .seealso: `MatGetRow()`
633 @*/
634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
635 {
636   PetscFunctionBegin;
637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
638   if (ncols) PetscValidIntPointer(ncols, 3);
639   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
640   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
641   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
642   if (ncols) *ncols = 0;
643   if (cols) *cols = NULL;
644   if (vals) *vals = NULL;
645   PetscFunctionReturn(PETSC_SUCCESS);
646 }
647 
648 /*@
649    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
650    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
651 
652    Not Collective
653 
654    Input Parameters:
655 .  mat - the matrix
656 
657    Note:
658    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.
659 
660    Level: advanced
661 
662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
663 @*/
664 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
665 {
666   PetscFunctionBegin;
667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
668   PetscValidType(mat, 1);
669   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
670   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
671   MatCheckPreallocated(mat, 1);
672   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
673   PetscUseTypeMethod(mat, getrowuppertriangular);
674   PetscFunctionReturn(PETSC_SUCCESS);
675 }
676 
677 /*@
678    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
679 
680    Not Collective
681 
682    Input Parameters:
683 .  mat - the matrix
684 
685    Note:
686    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
687 
688    Level: advanced
689 
690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
701   PetscUseTypeMethod(mat, restorerowuppertriangular);
702   PetscFunctionReturn(PETSC_SUCCESS);
703 }
704 
705 /*@C
706    MatSetOptionsPrefix - Sets the prefix used for searching for all
707    `Mat` options in the database.
708 
709    Logically Collective on A
710 
711    Input Parameters:
712 +  A - the matrix
713 -  prefix - the prefix to prepend to all option names
714 
715    Notes:
716    A hyphen (-) must NOT be given at the beginning of the prefix name.
717    The first character of all runtime options is AUTOMATICALLY the hyphen.
718 
719    This is NOT used for options for the factorization of the matrix. Normally the
720    prefix is automatically passed in from the PC calling the factorization. To set
721    it directly use  `MatSetOptionsPrefixFactor()`
722 
723    Level: advanced
724 
725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
726 @*/
727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
728 {
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
731   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
732   PetscFunctionReturn(PETSC_SUCCESS);
733 }
734 
735 /*@C
736    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
737    for matrices created with `MatGetFactor()`
738 
739    Logically Collective on A
740 
741    Input Parameters:
742 +  A - the matrix
743 -  prefix - the prefix to prepend to all option names for the factored matrix
744 
745    Notes:
746    A hyphen (-) must NOT be given at the beginning of the prefix name.
747    The first character of all runtime options is AUTOMATICALLY the hyphen.
748 
749    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
750    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
751 
752    Level: developer
753 
754 .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
755 @*/
756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
757 {
758   PetscFunctionBegin;
759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
760   if (prefix) {
761     PetscValidCharPointer(prefix, 2);
762     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
763     if (prefix != A->factorprefix) {
764       PetscCall(PetscFree(A->factorprefix));
765       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
766     }
767   } else PetscCall(PetscFree(A->factorprefix));
768   PetscFunctionReturn(PETSC_SUCCESS);
769 }
770 
771 /*@C
772    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
773    for matrices created with `MatGetFactor()`
774 
775    Logically Collective on A
776 
777    Input Parameters:
778 +  A - the matrix
779 -  prefix - the prefix to prepend to all option names for the factored matrix
780 
781    Notes:
782    A hyphen (-) must NOT be given at the beginning of the prefix name.
783    The first character of all runtime options is AUTOMATICALLY the hyphen.
784 
785    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
786    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
787 
788    Level: developer
789 
790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
791           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
792           `MatSetOptionsPrefix()`
793 @*/
794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
795 {
796   char  *buf = A->factorprefix;
797   size_t len1, len2;
798 
799   PetscFunctionBegin;
800   PetscValidHeader(A, 1);
801   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
802   if (!buf) {
803     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
804     PetscFunctionReturn(PETSC_SUCCESS);
805   }
806   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
807 
808   PetscCall(PetscStrlen(prefix, &len1));
809   PetscCall(PetscStrlen(buf, &len2));
810   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
811   PetscCall(PetscStrcpy(A->factorprefix, buf));
812   PetscCall(PetscStrcat(A->factorprefix, prefix));
813   PetscCall(PetscFree(buf));
814   PetscFunctionReturn(PETSC_SUCCESS);
815 }
816 
817 /*@C
818    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
819    matrix options in the database.
820 
821    Logically Collective on A
822 
823    Input Parameters:
824 +  A - the matrix
825 -  prefix - the prefix to prepend to all option names
826 
827    Note:
828    A hyphen (-) must NOT be given at the beginning of the prefix name.
829    The first character of all runtime options is AUTOMATICALLY the hyphen.
830 
831    Level: advanced
832 
833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
834 @*/
835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
836 {
837   PetscFunctionBegin;
838   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
839   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
840   PetscFunctionReturn(PETSC_SUCCESS);
841 }
842 
843 /*@C
844    MatGetOptionsPrefix - Gets the prefix used for searching for all
845    matrix options in the database.
846 
847    Not Collective
848 
849    Input Parameter:
850 .  A - the matrix
851 
852    Output Parameter:
853 .  prefix - pointer to the prefix string used
854 
855    Level: advanced
856 
857    Fortran Note:
858     On the fortran side, the user should pass in a string 'prefix' of
859    sufficient length to hold the prefix.
860 
861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
862 @*/
863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
864 {
865   PetscFunctionBegin;
866   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
867   PetscValidPointer(prefix, 2);
868   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
869   PetscFunctionReturn(PETSC_SUCCESS);
870 }
871 
872 /*@
873    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
874 
875    Collective on A
876 
877    Input Parameters:
878 .  A - the matrix
879 
880    Notes:
881    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
882 
883    Users can reset the preallocation to access the original memory.
884 
885    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
886 
887    Level: beginner
888 
889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
890 @*/
891 PetscErrorCode MatResetPreallocation(Mat A)
892 {
893   PetscFunctionBegin;
894   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
895   PetscValidType(A, 1);
896   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
897   PetscFunctionReturn(PETSC_SUCCESS);
898 }
899 
900 /*@
901    MatSetUp - Sets up the internal matrix data structures for later use.
902 
903    Collective on A
904 
905    Input Parameters:
906 .  A - the matrix
907 
908    Notes:
909    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
910 
911    If a suitable preallocation routine is used, this function does not need to be called.
912 
913    See the Performance chapter of the PETSc users manual for how to preallocate matrices
914 
915    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
916 
917    Level: intermediate
918 
919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
920 @*/
921 PetscErrorCode MatSetUp(Mat A)
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
925   if (!((PetscObject)A)->type_name) {
926     PetscMPIInt size;
927 
928     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
929     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
930   }
931   if (!A->preallocated && A->ops->setup) {
932     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
933     PetscUseTypeMethod(A, setup);
934   }
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 /*@C
946    MatViewFromOptions - View properties of the matrix from the options database
947 
948    Collective on A
949 
950    Input Parameters:
951 +  A - the matrix
952 .  obj - optional additional object that provides the options prefix to use
953 -  name - command line option
954 
955   Options Database Key:
956 .  -mat_view [viewertype]:... - the viewer and its options
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970    Level: intermediate
971 
972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
973 @*/
974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
975 {
976   PetscFunctionBegin;
977   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
978   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
979   PetscFunctionReturn(PETSC_SUCCESS);
980 }
981 
982 /*@C
983    MatView - display information about a matrix in a variety ways
984 
985    Collective
986 
987    Input Parameters:
988 +  mat - the matrix
989 -  viewer - visualization context
990 
991   Notes:
992   The available visualization contexts include
993 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
994 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
995 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
996 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
997 
998    The user can open alternative visualization contexts with
999 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1000 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1001          specified file; corresponding input uses MatLoad()
1002 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1003          an X window display
1004 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1005          Currently only the sequential dense and AIJ
1006          matrix types support the Socket viewer.
1007 
1008    The user can call `PetscViewerPushFormat()` to specify the output
1009    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1010    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1011 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1012 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1013 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1014 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1015          format common among all matrix types
1016 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1017          format (which is in many cases the same as the default)
1018 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1019          size and structure (not the matrix entries)
1020 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1021          the matrix structure
1022 
1023    Options Database Keys:
1024 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1025 .  -mat_view ::ascii_info_detail - Prints more detailed info
1026 .  -mat_view - Prints matrix in ASCII format
1027 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1028 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1029 .  -display <name> - Sets display name (default is host)
1030 .  -draw_pause <sec> - Sets number of seconds to pause after display
1031 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1032 .  -viewer_socket_machine <machine> -
1033 .  -viewer_socket_port <port> -
1034 .  -mat_view binary - save matrix to file in binary format
1035 -  -viewer_binary_filename <name> -
1036 
1037    Level: beginner
1038 
1039    Notes:
1040     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1041     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1042 
1043     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1044 
1045     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1046       viewer is used.
1047 
1048       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1049       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1050 
1051       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1052       and then use the following mouse functions.
1053 .vb
1054   left mouse: zoom in
1055   middle mouse: zoom out
1056   right mouse: continue with the simulation
1057 .ve
1058 
1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1060           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1061 @*/
1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1063 {
1064   PetscInt          rows, cols, rbs, cbs;
1065   PetscBool         isascii, isstring, issaws;
1066   PetscViewerFormat format;
1067   PetscMPIInt       size;
1068 
1069   PetscFunctionBegin;
1070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1071   PetscValidType(mat, 1);
1072   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1073   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1074   PetscCheckSameComm(mat, 1, viewer, 2);
1075 
1076   PetscCall(PetscViewerGetFormat(viewer, &format));
1077   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1078   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1079 
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1081   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1082   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1083   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");
1084 
1085   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1086   if (isascii) {
1087     if (!mat->preallocated) {
1088       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1089       PetscFunctionReturn(PETSC_SUCCESS);
1090     }
1091     if (!mat->assembled) {
1092       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1093       PetscFunctionReturn(PETSC_SUCCESS);
1094     }
1095     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1096     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1097       MatNullSpace nullsp, transnullsp;
1098 
1099       PetscCall(PetscViewerASCIIPushTab(viewer));
1100       PetscCall(MatGetSize(mat, &rows, &cols));
1101       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1102       if (rbs != 1 || cbs != 1) {
1103         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1104         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1105       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1106       if (mat->factortype) {
1107         MatSolverType solver;
1108         PetscCall(MatFactorGetSolverType(mat, &solver));
1109         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1110       }
1111       if (mat->ops->getinfo) {
1112         MatInfo info;
1113         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1114         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1115         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1116       }
1117       PetscCall(MatGetNullSpace(mat, &nullsp));
1118       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1120       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1121       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1122       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1123       PetscCall(PetscViewerASCIIPushTab(viewer));
1124       PetscCall(MatProductView(mat, viewer));
1125       PetscCall(PetscViewerASCIIPopTab(viewer));
1126     }
1127   } else if (issaws) {
1128 #if defined(PETSC_HAVE_SAWS)
1129     PetscMPIInt rank;
1130 
1131     PetscCall(PetscObjectName((PetscObject)mat));
1132     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1133     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1134 #endif
1135   } else if (isstring) {
1136     const char *type;
1137     PetscCall(MatGetType(mat, &type));
1138     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1139     PetscTryTypeMethod(mat, view, viewer);
1140   }
1141   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1142     PetscCall(PetscViewerASCIIPushTab(viewer));
1143     PetscUseTypeMethod(mat, viewnative, viewer);
1144     PetscCall(PetscViewerASCIIPopTab(viewer));
1145   } else if (mat->ops->view) {
1146     PetscCall(PetscViewerASCIIPushTab(viewer));
1147     PetscUseTypeMethod(mat, view, viewer);
1148     PetscCall(PetscViewerASCIIPopTab(viewer));
1149   }
1150   if (isascii) {
1151     PetscCall(PetscViewerGetFormat(viewer, &format));
1152     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1153   }
1154   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1155   PetscFunctionReturn(PETSC_SUCCESS);
1156 }
1157 
1158 #if defined(PETSC_USE_DEBUG)
1159   #include <../src/sys/totalview/tv_data_display.h>
1160 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1161 {
1162   TV_add_row("Local rows", "int", &mat->rmap->n);
1163   TV_add_row("Local columns", "int", &mat->cmap->n);
1164   TV_add_row("Global rows", "int", &mat->rmap->N);
1165   TV_add_row("Global columns", "int", &mat->cmap->N);
1166   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1167   return TV_format_OK;
1168 }
1169 #endif
1170 
1171 /*@C
1172    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1173    with `MatView()`.  The matrix format is determined from the options database.
1174    Generates a parallel MPI matrix if the communicator has more than one
1175    processor.  The default matrix type is `MATAIJ`.
1176 
1177    Collective
1178 
1179    Input Parameters:
1180 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1181             or some related function before a call to `MatLoad()`
1182 -  viewer - binary/HDF5 file viewer
1183 
1184    Options Database Keys:
1185    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1186    block size
1187 .    -matload_block_size <bs> - set block size
1188 
1189    Level: beginner
1190 
1191    Notes:
1192    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1193    `Mat` before calling this routine if you wish to set it from the options database.
1194 
1195    `MatLoad()` automatically loads into the options database any options
1196    given in the file filename.info where filename is the name of the file
1197    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1198    file will be ignored if you use the -viewer_binary_skip_info option.
1199 
1200    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1201    sets the default matrix type AIJ and sets the local and global sizes.
1202    If type and/or size is already set, then the same are used.
1203 
1204    In parallel, each processor can load a subset of rows (or the
1205    entire matrix).  This routine is especially useful when a large
1206    matrix is stored on disk and only part of it is desired on each
1207    processor.  For example, a parallel solver may access only some of
1208    the rows from each processor.  The algorithm used here reads
1209    relatively small blocks of data rather than reading the entire
1210    matrix and then subsetting it.
1211 
1212    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1213    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1214    or the sequence like
1215 .vb
1216     `PetscViewer` v;
1217     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1218     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1219     `PetscViewerSetFromOptions`(v);
1220     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1221     `PetscViewerFileSetName`(v,"datafile");
1222 .ve
1223    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1224 $ -viewer_type {binary,hdf5}
1225 
1226    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1227    and src/mat/tutorials/ex10.c with the second approach.
1228 
1229    Notes about the PETSc binary format:
1230    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1231    is read onto rank 0 and then shipped to its destination rank, one after another.
1232    Multiple objects, both matrices and vectors, can be stored within the same file.
1233    Their PetscObject name is ignored; they are loaded in the order of their storage.
1234 
1235    Most users should not need to know the details of the binary storage
1236    format, since `MatLoad()` and `MatView()` completely hide these details.
1237    But for anyone who's interested, the standard binary matrix storage
1238    format is
1239 
1240 $    PetscInt    MAT_FILE_CLASSID
1241 $    PetscInt    number of rows
1242 $    PetscInt    number of columns
1243 $    PetscInt    total number of nonzeros
1244 $    PetscInt    *number nonzeros in each row
1245 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1246 $    PetscScalar *values of all nonzeros
1247 
1248    PETSc automatically does the byte swapping for
1249 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1250 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1252 and `PetscBinaryWrite()` to see how this may be done.
1253 
1254    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1255    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1256    Each processor's chunk is loaded independently by its owning rank.
1257    Multiple objects, both matrices and vectors, can be stored within the same file.
1258    They are looked up by their PetscObject name.
1259 
1260    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1261    by default the same structure and naming of the AIJ arrays and column count
1262    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1263 $    save example.mat A b -v7.3
1264    can be directly read by this routine (see Reference 1 for details).
1265    Note that depending on your MATLAB version, this format might be a default,
1266    otherwise you can set it as default in Preferences.
1267 
1268    Unless -nocompression flag is used to save the file in MATLAB,
1269    PETSc must be configured with ZLIB package.
1270 
1271    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1272 
1273    Current HDF5 (MAT-File) limitations:
1274    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1275 
1276    Corresponding `MatView()` is not yet implemented.
1277 
1278    The loaded matrix is actually a transpose of the original one in MATLAB,
1279    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1280    With this format, matrix is automatically transposed by PETSc,
1281    unless the matrix is marked as SPD or symmetric
1282    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1283 
1284    References:
1285 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1286 
1287 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1288  @*/
1289 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1290 {
1291   PetscBool flg;
1292 
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1295   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1296 
1297   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1298 
1299   flg = PETSC_FALSE;
1300   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1301   if (flg) {
1302     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1303     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1304   }
1305   flg = PETSC_FALSE;
1306   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1307   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1308 
1309   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1310   PetscUseTypeMethod(mat, load, viewer);
1311   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1312   PetscFunctionReturn(PETSC_SUCCESS);
1313 }
1314 
1315 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1316 {
1317   Mat_Redundant *redund = *redundant;
1318 
1319   PetscFunctionBegin;
1320   if (redund) {
1321     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1322       PetscCall(ISDestroy(&redund->isrow));
1323       PetscCall(ISDestroy(&redund->iscol));
1324       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1325     } else {
1326       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1327       PetscCall(PetscFree(redund->sbuf_j));
1328       PetscCall(PetscFree(redund->sbuf_a));
1329       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1330         PetscCall(PetscFree(redund->rbuf_j[i]));
1331         PetscCall(PetscFree(redund->rbuf_a[i]));
1332       }
1333       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1334     }
1335 
1336     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1337     PetscCall(PetscFree(redund));
1338   }
1339   PetscFunctionReturn(PETSC_SUCCESS);
1340 }
1341 
1342 /*@C
1343    MatDestroy - Frees space taken by a matrix.
1344 
1345    Collective on A
1346 
1347    Input Parameter:
1348 .  A - the matrix
1349 
1350    Level: beginner
1351 
1352    Developer Note:
1353    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1354    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1355    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1356    if changes are needed here.
1357 
1358 .seealso: `Mat`, `MatCreate()`
1359 @*/
1360 PetscErrorCode MatDestroy(Mat *A)
1361 {
1362   PetscFunctionBegin;
1363   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1364   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1365   if (--((PetscObject)(*A))->refct > 0) {
1366     *A = NULL;
1367     PetscFunctionReturn(PETSC_SUCCESS);
1368   }
1369 
1370   /* if memory was published with SAWs then destroy it */
1371   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1372   PetscTryTypeMethod((*A), destroy);
1373 
1374   PetscCall(PetscFree((*A)->factorprefix));
1375   PetscCall(PetscFree((*A)->defaultvectype));
1376   PetscCall(PetscFree((*A)->defaultrandtype));
1377   PetscCall(PetscFree((*A)->bsizes));
1378   PetscCall(PetscFree((*A)->solvertype));
1379   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1380   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1381   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1382   PetscCall(MatProductClear(*A));
1383   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1384   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1385   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1386   PetscCall(MatDestroy(&(*A)->schur));
1387   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1388   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1389   PetscCall(PetscHeaderDestroy(A));
1390   PetscFunctionReturn(PETSC_SUCCESS);
1391 }
1392 
1393 /*@C
1394    MatSetValues - Inserts or adds a block of values into a matrix.
1395    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1396    MUST be called after all calls to `MatSetValues()` have been completed.
1397 
1398    Not Collective
1399 
1400    Input Parameters:
1401 +  mat - the matrix
1402 .  v - a logically two-dimensional array of values
1403 .  m, idxm - the number of rows and their global indices
1404 .  n, idxn - the number of columns and their global indices
1405 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1406 
1407    Notes:
1408    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1409       `MatSetUp()` before using this routine
1410 
1411    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1412 
1413    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1414    options cannot be mixed without intervening calls to the assembly
1415    routines.
1416 
1417    `MatSetValues()` uses 0-based row and column numbers in Fortran
1418    as well as in C.
1419 
1420    Negative indices may be passed in idxm and idxn, these rows and columns are
1421    simply ignored. This allows easily inserting element stiffness matrices
1422    with homogeneous Dirchlet boundary conditions that you don't want represented
1423    in the matrix.
1424 
1425    Efficiency Alert:
1426    The routine `MatSetValuesBlocked()` may offer much better efficiency
1427    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1428 
1429    Level: beginner
1430 
1431    Developer Note:
1432    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1433    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1434 
1435 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1436           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1437 @*/
1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1439 {
1440   PetscFunctionBeginHot;
1441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1442   PetscValidType(mat, 1);
1443   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1444   PetscValidIntPointer(idxm, 3);
1445   PetscValidIntPointer(idxn, 5);
1446   MatCheckPreallocated(mat, 1);
1447 
1448   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1449   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1450 
1451   if (PetscDefined(USE_DEBUG)) {
1452     PetscInt i, j;
1453 
1454     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1455     for (i = 0; i < m; i++) {
1456       for (j = 0; j < n; j++) {
1457         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1458 #if defined(PETSC_USE_COMPLEX)
1459           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]);
1460 #else
1461           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]);
1462 #endif
1463       }
1464     }
1465     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);
1466     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);
1467   }
1468 
1469   if (mat->assembled) {
1470     mat->was_assembled = PETSC_TRUE;
1471     mat->assembled     = PETSC_FALSE;
1472   }
1473   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1474   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1475   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1476   PetscFunctionReturn(PETSC_SUCCESS);
1477 }
1478 
1479 /*@C
1480    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1481    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1482    MUST be called after all calls to `MatSetValues()` have been completed.
1483 
1484    Not Collective
1485 
1486    Input Parameters:
1487 +  mat - the matrix
1488 .  v - a logically two-dimensional array of values
1489 .  ism - the rows to provide
1490 .  isn - the columns to provide
1491 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1492 
1493    Level: beginner
1494 
1495    Notes:
1496    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1497       `MatSetUp()` before using this routine
1498 
1499    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1500 
1501    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1502    options cannot be mixed without intervening calls to the assembly
1503    routines.
1504 
1505    `MatSetValues()` uses 0-based row and column numbers in Fortran
1506    as well as in C.
1507 
1508    Negative indices may be passed in ism and isn, these rows and columns are
1509    simply ignored. This allows easily inserting element stiffness matrices
1510    with homogeneous Dirchlet boundary conditions that you don't want represented
1511    in the matrix.
1512 
1513    Efficiency Alert:
1514    The routine `MatSetValuesBlocked()` may offer much better efficiency
1515    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1516 
1517     This is currently not optimized for any particular `ISType`
1518 
1519    Developer Notes:
1520     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1521                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1522 
1523 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1524           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1525 @*/
1526 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1527 {
1528   PetscInt        m, n;
1529   const PetscInt *rows, *cols;
1530 
1531   PetscFunctionBeginHot;
1532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1533   PetscCall(ISGetIndices(ism, &rows));
1534   PetscCall(ISGetIndices(isn, &cols));
1535   PetscCall(ISGetLocalSize(ism, &m));
1536   PetscCall(ISGetLocalSize(isn, &n));
1537   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1538   PetscCall(ISRestoreIndices(ism, &rows));
1539   PetscCall(ISRestoreIndices(isn, &cols));
1540   PetscFunctionReturn(PETSC_SUCCESS);
1541 }
1542 
1543 /*@
1544    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1545         values into a matrix
1546 
1547    Not Collective
1548 
1549    Input Parameters:
1550 +  mat - the matrix
1551 .  row - the (block) row to set
1552 -  v - a logically two-dimensional array of values
1553 
1554    Notes:
1555    By the values, v, are column-oriented (for the block version) and sorted
1556 
1557    All the nonzeros in the row must be provided
1558 
1559    The matrix must have previously had its column indices set
1560 
1561    The row must belong to this process
1562 
1563    Level: intermediate
1564 
1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1566           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1567 @*/
1568 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1569 {
1570   PetscInt globalrow;
1571 
1572   PetscFunctionBegin;
1573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1574   PetscValidType(mat, 1);
1575   PetscValidScalarPointer(v, 3);
1576   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1577   PetscCall(MatSetValuesRow(mat, globalrow, v));
1578   PetscFunctionReturn(PETSC_SUCCESS);
1579 }
1580 
1581 /*@
1582    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1583         values into a matrix
1584 
1585    Not Collective
1586 
1587    Input Parameters:
1588 +  mat - the matrix
1589 .  row - the (block) row to set
1590 -  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
1591 
1592    Notes:
1593    The values, v, are column-oriented for the block version.
1594 
1595    All the nonzeros in the row must be provided
1596 
1597    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1598 
1599    The row must belong to this process
1600 
1601    Level: advanced
1602 
1603 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1604           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1605 @*/
1606 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1607 {
1608   PetscFunctionBeginHot;
1609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1610   PetscValidType(mat, 1);
1611   MatCheckPreallocated(mat, 1);
1612   PetscValidScalarPointer(v, 3);
1613   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1614   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1615   mat->insertmode = INSERT_VALUES;
1616 
1617   if (mat->assembled) {
1618     mat->was_assembled = PETSC_TRUE;
1619     mat->assembled     = PETSC_FALSE;
1620   }
1621   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1622   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1623   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1624   PetscFunctionReturn(PETSC_SUCCESS);
1625 }
1626 
1627 /*@
1628    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1629      Using structured grid indexing
1630 
1631    Not Collective
1632 
1633    Input Parameters:
1634 +  mat - the matrix
1635 .  m - number of rows being entered
1636 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1637 .  n - number of columns being entered
1638 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1639 .  v - a logically two-dimensional array of values
1640 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1641 
1642    Level: beginner
1643 
1644    Notes:
1645    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1646 
1647    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1648    options cannot be mixed without intervening calls to the assembly
1649    routines.
1650 
1651    The grid coordinates are across the entire grid, not just the local portion
1652 
1653    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1654    as well as in C.
1655 
1656    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1657 
1658    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1659    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1660 
1661    The columns and rows in the stencil passed in MUST be contained within the
1662    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1663    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1664    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1665    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1666 
1667    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1668    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1669    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1670    `DM_BOUNDARY_PERIODIC` boundary type.
1671 
1672    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
1673    a single value per point) you can skip filling those indices.
1674 
1675    Inspired by the structured grid interface to the HYPRE package
1676    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1677 
1678    Efficiency Alert:
1679    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1680    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1681 
1682    Fortran Note:
1683    In Fortran idxm and idxn should be declared as
1684 $     MatStencil idxm(4,m),idxn(4,n)
1685    and the values inserted using
1686 .vb
1687     idxm(MatStencil_i,1) = i
1688     idxm(MatStencil_j,1) = j
1689     idxm(MatStencil_k,1) = k
1690     idxm(MatStencil_c,1) = c
1691     etc
1692 .ve
1693 
1694 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1695           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1696 @*/
1697 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1698 {
1699   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1700   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1701   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1702 
1703   PetscFunctionBegin;
1704   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1706   PetscValidType(mat, 1);
1707   PetscValidPointer(idxm, 3);
1708   PetscValidPointer(idxn, 5);
1709 
1710   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1711     jdxm = buf;
1712     jdxn = buf + m;
1713   } else {
1714     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1715     jdxm = bufm;
1716     jdxn = bufn;
1717   }
1718   for (i = 0; i < m; i++) {
1719     for (j = 0; j < 3 - sdim; j++) dxm++;
1720     tmp = *dxm++ - starts[0];
1721     for (j = 0; j < dim - 1; j++) {
1722       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1723       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1724     }
1725     if (mat->stencil.noc) dxm++;
1726     jdxm[i] = tmp;
1727   }
1728   for (i = 0; i < n; i++) {
1729     for (j = 0; j < 3 - sdim; j++) dxn++;
1730     tmp = *dxn++ - starts[0];
1731     for (j = 0; j < dim - 1; j++) {
1732       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1733       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1734     }
1735     if (mat->stencil.noc) dxn++;
1736     jdxn[i] = tmp;
1737   }
1738   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1739   PetscCall(PetscFree2(bufm, bufn));
1740   PetscFunctionReturn(PETSC_SUCCESS);
1741 }
1742 
1743 /*@
1744    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1745      Using structured grid indexing
1746 
1747    Not Collective
1748 
1749    Input Parameters:
1750 +  mat - the matrix
1751 .  m - number of rows being entered
1752 .  idxm - grid coordinates for matrix rows being entered
1753 .  n - number of columns being entered
1754 .  idxn - grid coordinates for matrix columns being entered
1755 .  v - a logically two-dimensional array of values
1756 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1757 
1758    Level: beginner
1759 
1760    Notes:
1761    By default the values, v, are row-oriented and unsorted.
1762    See `MatSetOption()` for other options.
1763 
1764    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1765    options cannot be mixed without intervening calls to the assembly
1766    routines.
1767 
1768    The grid coordinates are across the entire grid, not just the local portion
1769 
1770    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1771    as well as in C.
1772 
1773    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1774 
1775    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1776    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1777 
1778    The columns and rows in the stencil passed in MUST be contained within the
1779    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1780    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1781    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1782    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1783 
1784    Negative indices may be passed in idxm and idxn, these rows and columns are
1785    simply ignored. This allows easily inserting element stiffness matrices
1786    with homogeneous Dirchlet boundary conditions that you don't want represented
1787    in the matrix.
1788 
1789    Inspired by the structured grid interface to the HYPRE package
1790    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1791 
1792    Fortran Note:
1793    In Fortran idxm and idxn should be declared as
1794 $     MatStencil idxm(4,m),idxn(4,n)
1795    and the values inserted using
1796 .vb
1797     idxm(MatStencil_i,1) = i
1798     idxm(MatStencil_j,1) = j
1799     idxm(MatStencil_k,1) = k
1800    etc
1801 .ve
1802 
1803 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1804           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1805           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1806 @*/
1807 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1808 {
1809   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1810   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1811   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1812 
1813   PetscFunctionBegin;
1814   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1816   PetscValidType(mat, 1);
1817   PetscValidPointer(idxm, 3);
1818   PetscValidPointer(idxn, 5);
1819   PetscValidScalarPointer(v, 6);
1820 
1821   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1822     jdxm = buf;
1823     jdxn = buf + m;
1824   } else {
1825     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1826     jdxm = bufm;
1827     jdxn = bufn;
1828   }
1829   for (i = 0; i < m; i++) {
1830     for (j = 0; j < 3 - sdim; j++) dxm++;
1831     tmp = *dxm++ - starts[0];
1832     for (j = 0; j < sdim - 1; j++) {
1833       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1834       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1835     }
1836     dxm++;
1837     jdxm[i] = tmp;
1838   }
1839   for (i = 0; i < n; i++) {
1840     for (j = 0; j < 3 - sdim; j++) dxn++;
1841     tmp = *dxn++ - starts[0];
1842     for (j = 0; j < sdim - 1; j++) {
1843       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1844       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1845     }
1846     dxn++;
1847     jdxn[i] = tmp;
1848   }
1849   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1850   PetscCall(PetscFree2(bufm, bufn));
1851   PetscFunctionReturn(PETSC_SUCCESS);
1852 }
1853 
1854 /*@
1855    MatSetStencil - Sets the grid information for setting values into a matrix via
1856         `MatSetValuesStencil()`
1857 
1858    Not Collective
1859 
1860    Input Parameters:
1861 +  mat - the matrix
1862 .  dim - dimension of the grid 1, 2, or 3
1863 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1864 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1865 -  dof - number of degrees of freedom per node
1866 
1867    Notes:
1868    Inspired by the structured grid interface to the HYPRE package
1869    (www.llnl.gov/CASC/hyper)
1870 
1871    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1872    user.
1873 
1874    Level: beginner
1875 
1876 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1877           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1878 @*/
1879 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1880 {
1881   PetscFunctionBegin;
1882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1883   PetscValidIntPointer(dims, 3);
1884   PetscValidIntPointer(starts, 4);
1885 
1886   mat->stencil.dim = dim + (dof > 1);
1887   for (PetscInt i = 0; i < dim; i++) {
1888     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1889     mat->stencil.starts[i] = starts[dim - i - 1];
1890   }
1891   mat->stencil.dims[dim]   = dof;
1892   mat->stencil.starts[dim] = 0;
1893   mat->stencil.noc         = (PetscBool)(dof == 1);
1894   PetscFunctionReturn(PETSC_SUCCESS);
1895 }
1896 
1897 /*@C
1898    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1899 
1900    Not Collective
1901 
1902    Input Parameters:
1903 +  mat - the matrix
1904 .  v - a logically two-dimensional array of values
1905 .  m, idxm - the number of block rows and their global block indices
1906 .  n, idxn - the number of block columns and their global block indices
1907 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1908 
1909    Level: intermediate
1910 
1911    Notes:
1912    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1913    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1914 
1915    The m and n count the NUMBER of blocks in the row direction and column direction,
1916    NOT the total number of rows/columns; for example, if the block size is 2 and
1917    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1918    The values in idxm would be 1 2; that is the first index for each block divided by
1919    the block size.
1920 
1921    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1922    preallocating it).
1923 
1924    By default the values, v, are row-oriented, so the layout of
1925    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1926 
1927    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1928    options cannot be mixed without intervening calls to the assembly
1929    routines.
1930 
1931    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1932    as well as in C.
1933 
1934    Negative indices may be passed in idxm and idxn, these rows and columns are
1935    simply ignored. This allows easily inserting element stiffness matrices
1936    with homogeneous Dirchlet boundary conditions that you don't want represented
1937    in the matrix.
1938 
1939    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1940    internal searching must be done to determine where to place the
1941    data in the matrix storage space.  By instead inserting blocks of
1942    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1943    reduced.
1944 
1945    Example:
1946 .vb
1947    Suppose m=n=2 and block size(bs) = 2 The array is
1948 
1949    1  2  | 3  4
1950    5  6  | 7  8
1951    - - - | - - -
1952    9  10 | 11 12
1953    13 14 | 15 16
1954 
1955    v[] should be passed in like
1956    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1957 
1958   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1959    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1960 .ve
1961 
1962 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1963 @*/
1964 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1965 {
1966   PetscFunctionBeginHot;
1967   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1968   PetscValidType(mat, 1);
1969   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1970   PetscValidIntPointer(idxm, 3);
1971   PetscValidIntPointer(idxn, 5);
1972   MatCheckPreallocated(mat, 1);
1973   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1974   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1975   if (PetscDefined(USE_DEBUG)) {
1976     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1977     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1978   }
1979   if (PetscDefined(USE_DEBUG)) {
1980     PetscInt rbs, cbs, M, N, i;
1981     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1982     PetscCall(MatGetSize(mat, &M, &N));
1983     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);
1984     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);
1985   }
1986   if (mat->assembled) {
1987     mat->was_assembled = PETSC_TRUE;
1988     mat->assembled     = PETSC_FALSE;
1989   }
1990   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1991   if (mat->ops->setvaluesblocked) {
1992     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1993   } else {
1994     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1995     PetscInt i, j, bs, cbs;
1996 
1997     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1998     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1999       iidxm = buf;
2000       iidxn = buf + m * bs;
2001     } else {
2002       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2003       iidxm = bufr;
2004       iidxn = bufc;
2005     }
2006     for (i = 0; i < m; i++) {
2007       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2008     }
2009     if (m != n || bs != cbs || idxm != idxn) {
2010       for (i = 0; i < n; i++) {
2011         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2012       }
2013     } else iidxn = iidxm;
2014     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2015     PetscCall(PetscFree2(bufr, bufc));
2016   }
2017   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2018   PetscFunctionReturn(PETSC_SUCCESS);
2019 }
2020 
2021 /*@C
2022    MatGetValues - Gets a block of local values from a matrix.
2023 
2024    Not Collective; can only return values that are owned by the give process
2025 
2026    Input Parameters:
2027 +  mat - the matrix
2028 .  v - a logically two-dimensional array for storing the values
2029 .  m, idxm - the number of rows and their global indices
2030 -  n, idxn - the number of columns and their global indices
2031 
2032    Notes:
2033      The user must allocate space (m*n `PetscScalar`s) for the values, v.
2034      The values, v, are then returned in a row-oriented format,
2035      analogous to that used by default in `MatSetValues()`.
2036 
2037      `MatGetValues()` uses 0-based row and column numbers in
2038      Fortran as well as in C.
2039 
2040      `MatGetValues()` requires that the matrix has been assembled
2041      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2042      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2043      without intermediate matrix assembly.
2044 
2045      Negative row or column indices will be ignored and those locations in v[] will be
2046      left unchanged.
2047 
2048      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
2049      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2050      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2051 
2052    Level: advanced
2053 
2054 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2055 @*/
2056 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2057 {
2058   PetscFunctionBegin;
2059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2060   PetscValidType(mat, 1);
2061   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2062   PetscValidIntPointer(idxm, 3);
2063   PetscValidIntPointer(idxn, 5);
2064   PetscValidScalarPointer(v, 6);
2065   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2066   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2067   MatCheckPreallocated(mat, 1);
2068 
2069   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2070   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2071   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2072   PetscFunctionReturn(PETSC_SUCCESS);
2073 }
2074 
2075 /*@C
2076    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2077      defined previously by `MatSetLocalToGlobalMapping()`
2078 
2079    Not Collective
2080 
2081    Input Parameters:
2082 +  mat - the matrix
2083 .  nrow, irow - number of rows and their local indices
2084 -  ncol, icol - number of columns and their local indices
2085 
2086    Output Parameter:
2087 .  y -  a logically two-dimensional array of values
2088 
2089    Level: advanced
2090 
2091    Notes:
2092      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2093 
2094      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2095      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2096      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2097      with `MatSetLocalToGlobalMapping()`.
2098 
2099    Developer Note:
2100       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2101       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2102 
2103 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2104           `MatSetValuesLocal()`, `MatGetValues()`
2105 @*/
2106 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2107 {
2108   PetscFunctionBeginHot;
2109   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2110   PetscValidType(mat, 1);
2111   MatCheckPreallocated(mat, 1);
2112   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2113   PetscValidIntPointer(irow, 3);
2114   PetscValidIntPointer(icol, 5);
2115   if (PetscDefined(USE_DEBUG)) {
2116     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2117     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2118   }
2119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2120   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2121   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2122   else {
2123     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2124     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2125       irowm = buf;
2126       icolm = buf + nrow;
2127     } else {
2128       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2129       irowm = bufr;
2130       icolm = bufc;
2131     }
2132     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2134     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2135     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2136     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2137     PetscCall(PetscFree2(bufr, bufc));
2138   }
2139   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2140   PetscFunctionReturn(PETSC_SUCCESS);
2141 }
2142 
2143 /*@
2144   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2145   the same size. Currently, this can only be called once and creates the given matrix.
2146 
2147   Not Collective
2148 
2149   Input Parameters:
2150 + mat - the matrix
2151 . nb - the number of blocks
2152 . bs - the number of rows (and columns) in each block
2153 . rows - a concatenation of the rows for each block
2154 - v - a concatenation of logically two-dimensional arrays of values
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161   Level: advanced
2162 
2163 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2164           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2165 @*/
2166 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2167 {
2168   PetscFunctionBegin;
2169   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2170   PetscValidType(mat, 1);
2171   PetscValidIntPointer(rows, 4);
2172   PetscValidScalarPointer(v, 5);
2173   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2174 
2175   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2176   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2177   else {
2178     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2179   }
2180   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2181   PetscFunctionReturn(PETSC_SUCCESS);
2182 }
2183 
2184 /*@
2185    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2186    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2187    using a local (per-processor) numbering.
2188 
2189    Not Collective
2190 
2191    Input Parameters:
2192 +  x - the matrix
2193 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2194 -  cmapping - column mapping
2195 
2196    Level: intermediate
2197 
2198    Note:
2199    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2200 
2201 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2202 @*/
2203 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2204 {
2205   PetscFunctionBegin;
2206   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2207   PetscValidType(x, 1);
2208   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2209   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2210   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2211   else {
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2213     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2214   }
2215   PetscFunctionReturn(PETSC_SUCCESS);
2216 }
2217 
2218 /*@
2219    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2220 
2221    Not Collective
2222 
2223    Input Parameter:
2224 .  A - the matrix
2225 
2226    Output Parameters:
2227 + rmapping - row mapping
2228 - cmapping - column mapping
2229 
2230    Level: advanced
2231 
2232 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2233 @*/
2234 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2235 {
2236   PetscFunctionBegin;
2237   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2238   PetscValidType(A, 1);
2239   if (rmapping) {
2240     PetscValidPointer(rmapping, 2);
2241     *rmapping = A->rmap->mapping;
2242   }
2243   if (cmapping) {
2244     PetscValidPointer(cmapping, 3);
2245     *cmapping = A->cmap->mapping;
2246   }
2247   PetscFunctionReturn(PETSC_SUCCESS);
2248 }
2249 
2250 /*@
2251    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2252 
2253    Logically Collective on A
2254 
2255    Input Parameters:
2256 +  A - the matrix
2257 . rmap - row layout
2258 - cmap - column layout
2259 
2260    Level: advanced
2261 
2262    Note:
2263    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2264 
2265 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2266 @*/
2267 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2268 {
2269   PetscFunctionBegin;
2270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2271   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2272   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2273   PetscFunctionReturn(PETSC_SUCCESS);
2274 }
2275 
2276 /*@
2277    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2278 
2279    Not Collective
2280 
2281    Input Parameter:
2282 .  A - the matrix
2283 
2284    Output Parameters:
2285 + rmap - row layout
2286 - cmap - column layout
2287 
2288    Level: advanced
2289 
2290 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2291 @*/
2292 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2293 {
2294   PetscFunctionBegin;
2295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2296   PetscValidType(A, 1);
2297   if (rmap) {
2298     PetscValidPointer(rmap, 2);
2299     *rmap = A->rmap;
2300   }
2301   if (cmap) {
2302     PetscValidPointer(cmap, 3);
2303     *cmap = A->cmap;
2304   }
2305   PetscFunctionReturn(PETSC_SUCCESS);
2306 }
2307 
2308 /*@C
2309    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2310    using a local numbering of the nodes.
2311 
2312    Not Collective
2313 
2314    Input Parameters:
2315 +  mat - the matrix
2316 .  nrow, irow - number of rows and their local indices
2317 .  ncol, icol - number of columns and their local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Notes:
2322    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2323       `MatSetUp()` before using this routine
2324 
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2326 
2327    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2328    options cannot be mixed without intervening calls to the assembly
2329    routines.
2330 
2331    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2332    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2333 
2334    Level: intermediate
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow, irow - number of rows and their local indices
2402 .  ncol, icol - number of columns and their local indices
2403 .  y -  a logically two-dimensional array of values
2404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2405 
2406    Notes:
2407    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2408       `MatSetUp()` before using this routine
2409 
2410    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2411       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2412 
2413    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2414    options cannot be mixed without intervening calls to the assembly
2415    routines.
2416 
2417    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2418    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2419 
2420    Level: intermediate
2421 
2422    Developer Note:
2423     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2424                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2425 
2426 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2427           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2428 @*/
2429 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2430 {
2431   PetscFunctionBeginHot;
2432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2433   PetscValidType(mat, 1);
2434   MatCheckPreallocated(mat, 1);
2435   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2436   PetscValidIntPointer(irow, 3);
2437   PetscValidIntPointer(icol, 5);
2438   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2439   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2440   if (PetscDefined(USE_DEBUG)) {
2441     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2442     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);
2443   }
2444 
2445   if (mat->assembled) {
2446     mat->was_assembled = PETSC_TRUE;
2447     mat->assembled     = PETSC_FALSE;
2448   }
2449   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2450     PetscInt irbs, rbs;
2451     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2452     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2453     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2454   }
2455   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2456     PetscInt icbs, cbs;
2457     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2458     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2459     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2460   }
2461   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2462   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2463   else {
2464     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2465     const PetscInt *irowm, *icolm;
2466 
2467     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2468       bufr  = buf;
2469       bufc  = buf + nrow;
2470       irowm = bufr;
2471       icolm = bufc;
2472     } else {
2473       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2474       irowm = bufr;
2475       icolm = bufc;
2476     }
2477     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2478     else irowm = irow;
2479     if (mat->cmap->mapping) {
2480       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2481         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2482       } else icolm = irowm;
2483     } else icolm = icol;
2484     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2485     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2486   }
2487   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2488   PetscFunctionReturn(PETSC_SUCCESS);
2489 }
2490 
2491 /*@
2492    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2493 
2494    Collective
2495 
2496    Input Parameters:
2497 +  mat - the matrix
2498 -  x   - the vector to be multiplied
2499 
2500    Output Parameters:
2501 .  y - the result
2502 
2503    Note:
2504    The vectors x and y cannot be the same.  I.e., one cannot
2505    call `MatMultDiagonalBlock`(A,y,y).
2506 
2507    Level: developer
2508 
2509 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2510 @*/
2511 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2512 {
2513   PetscFunctionBegin;
2514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2515   PetscValidType(mat, 1);
2516   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2517   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2518 
2519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2521   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2522   MatCheckPreallocated(mat, 1);
2523 
2524   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2525   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2526   PetscFunctionReturn(PETSC_SUCCESS);
2527 }
2528 
2529 /* --------------------------------------------------------*/
2530 /*@
2531    MatMult - Computes the matrix-vector product, y = Ax.
2532 
2533    Neighbor-wise Collective
2534 
2535    Input Parameters:
2536 +  mat - the matrix
2537 -  x   - the vector to be multiplied
2538 
2539    Output Parameters:
2540 .  y - the result
2541 
2542    Note:
2543    The vectors x and y cannot be the same.  I.e., one cannot
2544    call `MatMult`(A,y,y).
2545 
2546    Level: beginner
2547 
2548 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2549 @*/
2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2551 {
2552   PetscFunctionBegin;
2553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2554   PetscValidType(mat, 1);
2555   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2556   VecCheckAssembled(x);
2557   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2559   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2560   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2561   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);
2562   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);
2563   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);
2564   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);
2565   PetscCall(VecSetErrorIfLocked(y, 3));
2566   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2567   MatCheckPreallocated(mat, 1);
2568 
2569   PetscCall(VecLockReadPush(x));
2570   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2571   PetscUseTypeMethod(mat, mult, x, y);
2572   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2573   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2574   PetscCall(VecLockReadPop(x));
2575   PetscFunctionReturn(PETSC_SUCCESS);
2576 }
2577 
2578 /*@
2579    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2580 
2581    Neighbor-wise Collective
2582 
2583    Input Parameters:
2584 +  mat - the matrix
2585 -  x   - the vector to be multiplied
2586 
2587    Output Parameters:
2588 .  y - the result
2589 
2590    Notes:
2591    The vectors x and y cannot be the same.  I.e., one cannot
2592    call `MatMultTranspose`(A,y,y).
2593 
2594    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2595    use `MatMultHermitianTranspose()`
2596 
2597    Level: beginner
2598 
2599 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2600 @*/
2601 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2602 {
2603   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2604 
2605   PetscFunctionBegin;
2606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2607   PetscValidType(mat, 1);
2608   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2609   VecCheckAssembled(x);
2610   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2611 
2612   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2613   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2614   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2615   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);
2616   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);
2617   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);
2618   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);
2619   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2620   MatCheckPreallocated(mat, 1);
2621 
2622   if (!mat->ops->multtranspose) {
2623     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2624     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);
2625   } else op = mat->ops->multtranspose;
2626   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2627   PetscCall(VecLockReadPush(x));
2628   PetscCall((*op)(mat, x, y));
2629   PetscCall(VecLockReadPop(x));
2630   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2631   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2632   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2633   PetscFunctionReturn(PETSC_SUCCESS);
2634 }
2635 
2636 /*@
2637    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2638 
2639    Neighbor-wise Collective
2640 
2641    Input Parameters:
2642 +  mat - the matrix
2643 -  x   - the vector to be multilplied
2644 
2645    Output Parameters:
2646 .  y - the result
2647 
2648    Notes:
2649    The vectors x and y cannot be the same.  I.e., one cannot
2650    call `MatMultHermitianTranspose`(A,y,y).
2651 
2652    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2653 
2654    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2655 
2656    Level: beginner
2657 
2658 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2659 @*/
2660 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2661 {
2662   PetscFunctionBegin;
2663   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2664   PetscValidType(mat, 1);
2665   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2666   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2667 
2668   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2669   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2670   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2671   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);
2672   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);
2673   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);
2674   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);
2675   MatCheckPreallocated(mat, 1);
2676 
2677   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2678 #if defined(PETSC_USE_COMPLEX)
2679   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2680     PetscCall(VecLockReadPush(x));
2681     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2682     else PetscUseTypeMethod(mat, mult, x, y);
2683     PetscCall(VecLockReadPop(x));
2684   } else {
2685     Vec w;
2686     PetscCall(VecDuplicate(x, &w));
2687     PetscCall(VecCopy(x, w));
2688     PetscCall(VecConjugate(w));
2689     PetscCall(MatMultTranspose(mat, w, y));
2690     PetscCall(VecDestroy(&w));
2691     PetscCall(VecConjugate(y));
2692   }
2693   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2694 #else
2695   PetscCall(MatMultTranspose(mat, x, y));
2696 #endif
2697   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2698   PetscFunctionReturn(PETSC_SUCCESS);
2699 }
2700 
2701 /*@
2702     MatMultAdd -  Computes v3 = v2 + A * v1.
2703 
2704     Neighbor-wise Collective
2705 
2706     Input Parameters:
2707 +   mat - the matrix
2708 -   v1, v2 - the vectors
2709 
2710     Output Parameters:
2711 .   v3 - the result
2712 
2713     Note:
2714     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2715     call `MatMultAdd`(A,v1,v2,v1).
2716 
2717     Level: beginner
2718 
2719 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2720 @*/
2721 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2722 {
2723   PetscFunctionBegin;
2724   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2725   PetscValidType(mat, 1);
2726   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2727   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2728   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2729 
2730   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2731   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2732   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);
2733   /* 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);
2734      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); */
2735   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);
2736   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);
2737   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2738   MatCheckPreallocated(mat, 1);
2739 
2740   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2741   PetscCall(VecLockReadPush(v1));
2742   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2743   PetscCall(VecLockReadPop(v1));
2744   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2745   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2746   PetscFunctionReturn(PETSC_SUCCESS);
2747 }
2748 
2749 /*@
2750    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2751 
2752    Neighbor-wise Collective
2753 
2754    Input Parameters:
2755 +  mat - the matrix
2756 -  v1, v2 - the vectors
2757 
2758    Output Parameters:
2759 .  v3 - the result
2760 
2761    Note:
2762    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2763    call `MatMultTransposeAdd`(A,v1,v2,v1).
2764 
2765    Level: beginner
2766 
2767 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2768 @*/
2769 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2770 {
2771   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2772 
2773   PetscFunctionBegin;
2774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2775   PetscValidType(mat, 1);
2776   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2777   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2778   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2779 
2780   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2781   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2782   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);
2783   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);
2784   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);
2785   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2786   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2787   MatCheckPreallocated(mat, 1);
2788 
2789   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2790   PetscCall(VecLockReadPush(v1));
2791   PetscCall((*op)(mat, v1, v2, v3));
2792   PetscCall(VecLockReadPop(v1));
2793   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2794   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2795   PetscFunctionReturn(PETSC_SUCCESS);
2796 }
2797 
2798 /*@
2799    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2800 
2801    Neighbor-wise Collective
2802 
2803    Input Parameters:
2804 +  mat - the matrix
2805 -  v1, v2 - the vectors
2806 
2807    Output Parameters:
2808 .  v3 - the result
2809 
2810    Note:
2811    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2812    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2813 
2814    Level: beginner
2815 
2816 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2817 @*/
2818 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2819 {
2820   PetscFunctionBegin;
2821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2822   PetscValidType(mat, 1);
2823   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2824   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2825   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2826 
2827   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2828   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2829   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2830   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);
2831   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);
2832   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);
2833   MatCheckPreallocated(mat, 1);
2834 
2835   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2836   PetscCall(VecLockReadPush(v1));
2837   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2838   else {
2839     Vec w, z;
2840     PetscCall(VecDuplicate(v1, &w));
2841     PetscCall(VecCopy(v1, w));
2842     PetscCall(VecConjugate(w));
2843     PetscCall(VecDuplicate(v3, &z));
2844     PetscCall(MatMultTranspose(mat, w, z));
2845     PetscCall(VecDestroy(&w));
2846     PetscCall(VecConjugate(z));
2847     if (v2 != v3) {
2848       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2849     } else {
2850       PetscCall(VecAXPY(v3, 1.0, z));
2851     }
2852     PetscCall(VecDestroy(&z));
2853   }
2854   PetscCall(VecLockReadPop(v1));
2855   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2856   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2857   PetscFunctionReturn(PETSC_SUCCESS);
2858 }
2859 
2860 /*@C
2861    MatGetFactorType - gets the type of factorization it is
2862 
2863    Not Collective
2864 
2865    Input Parameters:
2866 .  mat - the matrix
2867 
2868    Output Parameters:
2869 .  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`
2870 
2871    Level: intermediate
2872 
2873 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2874           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2875 @*/
2876 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2877 {
2878   PetscFunctionBegin;
2879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2880   PetscValidType(mat, 1);
2881   PetscValidPointer(t, 2);
2882   *t = mat->factortype;
2883   PetscFunctionReturn(PETSC_SUCCESS);
2884 }
2885 
2886 /*@C
2887    MatSetFactorType - sets the type of factorization it is
2888 
2889    Logically Collective
2890 
2891    Input Parameters:
2892 +  mat - the matrix
2893 -  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`
2894 
2895    Level: intermediate
2896 
2897 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2898           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2899 @*/
2900 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2901 {
2902   PetscFunctionBegin;
2903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2904   PetscValidType(mat, 1);
2905   mat->factortype = t;
2906   PetscFunctionReturn(PETSC_SUCCESS);
2907 }
2908 
2909 /* ------------------------------------------------------------*/
2910 /*@C
2911    MatGetInfo - Returns information about matrix storage (number of
2912    nonzeros, memory, etc.).
2913 
2914    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2915 
2916    Input Parameter:
2917 .  mat - the matrix
2918 
2919    Output Parameters:
2920 +  flag - flag indicating the type of parameters to be returned
2921    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2922    MAT_GLOBAL_SUM - sum over all processors)
2923 -  info - matrix information context
2924 
2925    Notes:
2926    The `MatInfo` context contains a variety of matrix data, including
2927    number of nonzeros allocated and used, number of mallocs during
2928    matrix assembly, etc.  Additional information for factored matrices
2929    is provided (such as the fill ratio, number of mallocs during
2930    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2931    when using the runtime options
2932 $       -info -mat_view ::ascii_info
2933 
2934    Example for C/C++ Users:
2935    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2936    data within the MatInfo context.  For example,
2937 .vb
2938       MatInfo info;
2939       Mat     A;
2940       double  mal, nz_a, nz_u;
2941 
2942       MatGetInfo(A,MAT_LOCAL,&info);
2943       mal  = info.mallocs;
2944       nz_a = info.nz_allocated;
2945 .ve
2946 
2947    Example for Fortran Users:
2948    Fortran users should declare info as a double precision
2949    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2950    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2951    a complete list of parameter names.
2952 .vb
2953       double  precision info(MAT_INFO_SIZE)
2954       double  precision mal, nz_a
2955       Mat     A
2956       integer ierr
2957 
2958       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2959       mal = info(MAT_INFO_MALLOCS)
2960       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2961 .ve
2962 
2963     Level: intermediate
2964 
2965     Developer Note:
2966     Fortran interface is not autogenerated as the
2967     interface definition cannot be generated correctly [due to MatInfo]
2968 
2969 .seealso: `MatInfo`, `MatStashGetInfo()`
2970 @*/
2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2972 {
2973   PetscFunctionBegin;
2974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2975   PetscValidType(mat, 1);
2976   PetscValidPointer(info, 3);
2977   MatCheckPreallocated(mat, 1);
2978   PetscUseTypeMethod(mat, getinfo, flag, info);
2979   PetscFunctionReturn(PETSC_SUCCESS);
2980 }
2981 
2982 /*
2983    This is used by external packages where it is not easy to get the info from the actual
2984    matrix factorization.
2985 */
2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2987 {
2988   PetscFunctionBegin;
2989   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2990   PetscFunctionReturn(PETSC_SUCCESS);
2991 }
2992 
2993 /* ----------------------------------------------------------*/
2994 
2995 /*@C
2996    MatLUFactor - Performs in-place LU factorization of matrix.
2997 
2998    Collective
2999 
3000    Input Parameters:
3001 +  mat - the matrix
3002 .  row - row permutation
3003 .  col - column permutation
3004 -  info - options for factorization, includes
3005 $          fill - expected fill as ratio of original fill.
3006 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007 $                   Run with the option -info to determine an optimal value to use
3008 
3009    Notes:
3010    Most users should employ the `KSP` interface for linear solvers
3011    instead of working directly with matrix algebra routines such as this.
3012    See, e.g., `KSPCreate()`.
3013 
3014    This changes the state of the matrix to a factored matrix; it cannot be used
3015    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3016 
3017    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3018    when not using `KSP`.
3019 
3020    Level: developer
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 $      levels - number of levels of fill.
3065 $      expected fill - as ratio of original fill.
3066 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3067                 missing diagonal entries)
3068 
3069    Level: developer
3070 
3071    Notes:
3072    Most users should employ the `KSP` interface for linear solvers
3073    instead of working directly with matrix algebra routines such as this.
3074    See, e.g., `KSPCreate()`.
3075 
3076    Probably really in-place only when level of fill is zero, otherwise allocates
3077    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3078    when not using `KSP`.
3079 
3080    Developer Note:
3081    The Fortran interface is not autogenerated as the
3082    interface definition cannot be generated correctly [due to MatFactorInfo]
3083 
3084 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3085 @*/
3086 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3087 {
3088   PetscFunctionBegin;
3089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3090   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3091   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3092   PetscValidPointer(info, 4);
3093   PetscValidType(mat, 1);
3094   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3096   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3097   MatCheckPreallocated(mat, 1);
3098 
3099   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3100   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3101   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3102   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3103   PetscFunctionReturn(PETSC_SUCCESS);
3104 }
3105 
3106 /*@C
3107    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3108    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3109 
3110    Collective on fact
3111 
3112    Input Parameters:
3113 +  fact - the factor matrix obtained with `MatGetFactor()`
3114 .  mat - the matrix
3115 .  row, col - row and column permutations
3116 -  info - options for factorization, includes
3117 .vb
3118           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3119           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3120 .ve
3121 
3122    Level: developer
3123 
3124    Notes:
3125     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3126 
3127    Most users should employ the simplified `KSP` interface for linear solvers
3128    instead of working directly with matrix algebra routines such as this.
3129    See, e.g., `KSPCreate()`.
3130 
3131    Developer Note:
3132    The Fortran interface is not autogenerated as the
3133    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3134 
3135 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3136 @*/
3137 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3138 {
3139   MatFactorInfo tinfo;
3140 
3141   PetscFunctionBegin;
3142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3143   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3144   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3145   if (info) PetscValidPointer(info, 5);
3146   PetscValidType(mat, 2);
3147   PetscValidPointer(fact, 1);
3148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3149   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3150   if (!(fact)->ops->lufactorsymbolic) {
3151     MatSolverType stype;
3152     PetscCall(MatFactorGetSolverType(fact, &stype));
3153     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3154   }
3155   MatCheckPreallocated(mat, 2);
3156   if (!info) {
3157     PetscCall(MatFactorInfoInitialize(&tinfo));
3158     info = &tinfo;
3159   }
3160 
3161   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3162   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3163   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3164   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3165   PetscFunctionReturn(PETSC_SUCCESS);
3166 }
3167 
3168 /*@C
3169    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3170    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3171 
3172    Collective on fact
3173 
3174    Input Parameters:
3175 +  fact - the factor matrix obtained with `MatGetFactor()`
3176 .  mat - the matrix
3177 -  info - options for factorization
3178 
3179    Level: developer
3180 
3181    Notes:
3182    See `MatLUFactor()` for in-place factorization.  See
3183    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3184 
3185    Most users should employ the `KSP` interface for linear solvers
3186    instead of working directly with matrix algebra routines such as this.
3187    See, e.g., `KSPCreate()`.
3188 
3189     Developer Note:
3190     The Fortran interface is not autogenerated as the
3191     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3192 
3193 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3194 @*/
3195 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3196 {
3197   MatFactorInfo tinfo;
3198 
3199   PetscFunctionBegin;
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3201   PetscValidType(mat, 2);
3202   PetscValidPointer(fact, 1);
3203   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3205   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,
3206              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3207 
3208   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3209   MatCheckPreallocated(mat, 2);
3210   if (!info) {
3211     PetscCall(MatFactorInfoInitialize(&tinfo));
3212     info = &tinfo;
3213   }
3214 
3215   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3216   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3217   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3218   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3219   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3220   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3221   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3222   PetscFunctionReturn(PETSC_SUCCESS);
3223 }
3224 
3225 /*@C
3226    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3227    symmetric matrix.
3228 
3229    Collective
3230 
3231    Input Parameters:
3232 +  mat - the matrix
3233 .  perm - row and column permutations
3234 -  f - expected fill as ratio of original fill
3235 
3236    Level: developer
3237 
3238    Notes:
3239    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3240    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3241 
3242    Most users should employ the `KSP` interface for linear solvers
3243    instead of working directly with matrix algebra routines such as this.
3244    See, e.g., `KSPCreate()`.
3245 
3246    Developer Note:
3247    The Fortran interface is not autogenerated as the
3248    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3249 
3250 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3251           `MatGetOrdering()`
3252 @*/
3253 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3254 {
3255   MatFactorInfo tinfo;
3256 
3257   PetscFunctionBegin;
3258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3259   PetscValidType(mat, 1);
3260   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3261   if (info) PetscValidPointer(info, 3);
3262   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3263   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3264   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3265   MatCheckPreallocated(mat, 1);
3266   if (!info) {
3267     PetscCall(MatFactorInfoInitialize(&tinfo));
3268     info = &tinfo;
3269   }
3270 
3271   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3272   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3273   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3274   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3275   PetscFunctionReturn(PETSC_SUCCESS);
3276 }
3277 
3278 /*@C
3279    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3280    of a symmetric matrix.
3281 
3282    Collective on fact
3283 
3284    Input Parameters:
3285 +  fact - the factor matrix obtained with `MatGetFactor()`
3286 .  mat - the matrix
3287 .  perm - row and column permutations
3288 -  info - options for factorization, includes
3289 .vb
3290           fill - expected fill as ratio of original fill.
3291           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3292                    Run with the option -info to determine an optimal value to use
3293 .ve
3294 
3295    Level: developer
3296 
3297    Notes:
3298    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3299    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3300 
3301    Most users should employ the `KSP` interface for linear solvers
3302    instead of working directly with matrix algebra routines such as this.
3303    See, e.g., `KSPCreate()`.
3304 
3305    Developer Note:
3306    The Fortran interface is not autogenerated as the
3307    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3308 
3309 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3310           `MatGetOrdering()`
3311 @*/
3312 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3313 {
3314   MatFactorInfo tinfo;
3315 
3316   PetscFunctionBegin;
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   PetscValidType(mat, 2);
3319   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3320   if (info) PetscValidPointer(info, 4);
3321   PetscValidPointer(fact, 1);
3322   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3325   if (!(fact)->ops->choleskyfactorsymbolic) {
3326     MatSolverType stype;
3327     PetscCall(MatFactorGetSolverType(fact, &stype));
3328     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3329   }
3330   MatCheckPreallocated(mat, 2);
3331   if (!info) {
3332     PetscCall(MatFactorInfoInitialize(&tinfo));
3333     info = &tinfo;
3334   }
3335 
3336   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3337   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3338   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3339   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3340   PetscFunctionReturn(PETSC_SUCCESS);
3341 }
3342 
3343 /*@C
3344    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3345    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3346    `MatCholeskyFactorSymbolic()`.
3347 
3348    Collective on fact
3349 
3350    Input Parameters:
3351 +  fact - the factor matrix obtained with `MatGetFactor()`
3352 .  mat - the initial matrix
3353 .  info - options for factorization
3354 -  fact - the symbolic factor of mat
3355 
3356    Level: developer
3357 
3358    Note:
3359    Most users should employ the `KSP` interface for linear solvers
3360    instead of working directly with matrix algebra routines such as this.
3361    See, e.g., `KSPCreate()`.
3362 
3363    Developer Note:
3364    The Fortran interface is not autogenerated as the
3365    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3366 
3367 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3368 @*/
3369 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3370 {
3371   MatFactorInfo tinfo;
3372 
3373   PetscFunctionBegin;
3374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3375   PetscValidType(mat, 2);
3376   PetscValidPointer(fact, 1);
3377   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3379   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3380   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,
3381              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3382   MatCheckPreallocated(mat, 2);
3383   if (!info) {
3384     PetscCall(MatFactorInfoInitialize(&tinfo));
3385     info = &tinfo;
3386   }
3387 
3388   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3389   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3390   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3391   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3392   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3393   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3394   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3395   PetscFunctionReturn(PETSC_SUCCESS);
3396 }
3397 
3398 /*@
3399    MatQRFactor - Performs in-place QR factorization of matrix.
3400 
3401    Collective
3402 
3403    Input Parameters:
3404 +  mat - the matrix
3405 .  col - column permutation
3406 -  info - options for factorization, includes
3407 .vb
3408           fill - expected fill as ratio of original fill.
3409           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3410                    Run with the option -info to determine an optimal value to use
3411 .ve
3412 
3413    Level: developer
3414 
3415    Notes:
3416    Most users should employ the `KSP` interface for linear solvers
3417    instead of working directly with matrix algebra routines such as this.
3418    See, e.g., `KSPCreate()`.
3419 
3420    This changes the state of the matrix to a factored matrix; it cannot be used
3421    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3422 
3423    Developer Note:
3424    The Fortran interface is not autogenerated as the
3425    interface definition cannot be generated correctly [due to MatFactorInfo]
3426 
3427 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3428           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3429 @*/
3430 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3431 {
3432   PetscFunctionBegin;
3433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3434   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3435   if (info) PetscValidPointer(info, 3);
3436   PetscValidType(mat, 1);
3437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3439   MatCheckPreallocated(mat, 1);
3440   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3441   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3442   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3443   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3444   PetscFunctionReturn(PETSC_SUCCESS);
3445 }
3446 
3447 /*@
3448    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3449    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3450 
3451    Collective on fact
3452 
3453    Input Parameters:
3454 +  fact - the factor matrix obtained with `MatGetFactor()`
3455 .  mat - the matrix
3456 .  col - column permutation
3457 -  info - options for factorization, includes
3458 .vb
3459           fill - expected fill as ratio of original fill.
3460           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3461                    Run with the option -info to determine an optimal value to use
3462 .ve
3463 
3464    Level: developer
3465 
3466    Note:
3467    Most users should employ the `KSP` interface for linear solvers
3468    instead of working directly with matrix algebra routines such as this.
3469    See, e.g., `KSPCreate()`.
3470 
3471    Developer Note:
3472    The Fortran interface is not autogenerated as the
3473    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3474 
3475 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3476 @*/
3477 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3478 {
3479   MatFactorInfo tinfo;
3480 
3481   PetscFunctionBegin;
3482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3483   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3484   if (info) PetscValidPointer(info, 4);
3485   PetscValidType(mat, 2);
3486   PetscValidPointer(fact, 1);
3487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3489   MatCheckPreallocated(mat, 2);
3490   if (!info) {
3491     PetscCall(MatFactorInfoInitialize(&tinfo));
3492     info = &tinfo;
3493   }
3494 
3495   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3496   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3497   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3498   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3499   PetscFunctionReturn(PETSC_SUCCESS);
3500 }
3501 
3502 /*@
3503    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3504    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3505 
3506    Collective on fact
3507 
3508    Input Parameters:
3509 +  fact - the factor matrix obtained with `MatGetFactor()`
3510 .  mat - the matrix
3511 -  info - options for factorization
3512 
3513    Level: developer
3514 
3515    Notes:
3516    See `MatQRFactor()` for in-place factorization.
3517 
3518    Most users should employ the `KSP` interface for linear solvers
3519    instead of working directly with matrix algebra routines such as this.
3520    See, e.g., `KSPCreate()`.
3521 
3522    Developer Note:
3523    The Fortran interface is not autogenerated as the
3524    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3525 
3526 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3527 @*/
3528 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3529 {
3530   MatFactorInfo tinfo;
3531 
3532   PetscFunctionBegin;
3533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3534   PetscValidType(mat, 2);
3535   PetscValidPointer(fact, 1);
3536   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3537   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3538   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,
3539              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3540 
3541   MatCheckPreallocated(mat, 2);
3542   if (!info) {
3543     PetscCall(MatFactorInfoInitialize(&tinfo));
3544     info = &tinfo;
3545   }
3546 
3547   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3548   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3549   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3550   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3551   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3552   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3553   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3554   PetscFunctionReturn(PETSC_SUCCESS);
3555 }
3556 
3557 /* ----------------------------------------------------------------*/
3558 /*@
3559    MatSolve - Solves A x = b, given a factored matrix.
3560 
3561    Neighbor-wise Collective
3562 
3563    Input Parameters:
3564 +  mat - the factored matrix
3565 -  b - the right-hand-side vector
3566 
3567    Output Parameter:
3568 .  x - the result vector
3569 
3570    Notes:
3571    The vectors b and x cannot be the same.  I.e., one cannot
3572    call `MatSolve`(A,x,x).
3573 
3574    Most users should employ the `KSP` interface for linear solvers
3575    instead of working directly with matrix algebra routines such as this.
3576    See, e.g., `KSPCreate()`.
3577 
3578    Level: developer
3579 
3580 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3581 @*/
3582 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3583 {
3584   PetscFunctionBegin;
3585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3586   PetscValidType(mat, 1);
3587   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3588   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3589   PetscCheckSameComm(mat, 1, b, 2);
3590   PetscCheckSameComm(mat, 1, x, 3);
3591   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3592   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);
3593   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);
3594   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);
3595   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3596   MatCheckPreallocated(mat, 1);
3597 
3598   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3599   if (mat->factorerrortype) {
3600     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3601     PetscCall(VecSetInf(x));
3602   } else PetscUseTypeMethod(mat, solve, b, x);
3603   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3604   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3605   PetscFunctionReturn(PETSC_SUCCESS);
3606 }
3607 
3608 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3609 {
3610   Vec      b, x;
3611   PetscInt N, i;
3612   PetscErrorCode (*f)(Mat, Vec, Vec);
3613   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3614 
3615   PetscFunctionBegin;
3616   if (A->factorerrortype) {
3617     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3618     PetscCall(MatSetInf(X));
3619     PetscFunctionReturn(PETSC_SUCCESS);
3620   }
3621   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3622   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3623   PetscCall(MatBoundToCPU(A, &Abound));
3624   if (!Abound) {
3625     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3626     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3627   }
3628 #if defined(PETSC_HAVE_CUDA)
3629   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3630   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3631 #elif (PETSC_HAVE_HIP)
3632   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3633   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3634 #endif
3635   PetscCall(MatGetSize(B, NULL, &N));
3636   for (i = 0; i < N; i++) {
3637     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3638     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3639     PetscCall((*f)(A, b, x));
3640     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3641     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3642   }
3643   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3644   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3645   PetscFunctionReturn(PETSC_SUCCESS);
3646 }
3647 
3648 /*@
3649    MatMatSolve - Solves A X = B, given a factored matrix.
3650 
3651    Neighbor-wise Collective on A
3652 
3653    Input Parameters:
3654 +  A - the factored matrix
3655 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3656 
3657    Output Parameter:
3658 .  X - the result matrix (dense matrix)
3659 
3660    Note:
3661    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3662    otherwise, B and X cannot be the same.
3663 
3664    Level: developer
3665 
3666 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3667 @*/
3668 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3669 {
3670   PetscFunctionBegin;
3671   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3672   PetscValidType(A, 1);
3673   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3674   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3675   PetscCheckSameComm(A, 1, B, 2);
3676   PetscCheckSameComm(A, 1, X, 3);
3677   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);
3678   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);
3679   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");
3680   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3681   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3682   MatCheckPreallocated(A, 1);
3683 
3684   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3685   if (!A->ops->matsolve) {
3686     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3687     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3688   } else PetscUseTypeMethod(A, matsolve, B, X);
3689   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3690   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3691   PetscFunctionReturn(PETSC_SUCCESS);
3692 }
3693 
3694 /*@
3695    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3696 
3697    Neighbor-wise Collective on A
3698 
3699    Input Parameters:
3700 +  A - the factored matrix
3701 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3702 
3703    Output Parameter:
3704 .  X - the result matrix (dense matrix)
3705 
3706    Note:
3707    The matrices B and X cannot be the same.  I.e., one cannot
3708    call `MatMatSolveTranspose`(A,X,X).
3709 
3710    Level: developer
3711 
3712 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3713 @*/
3714 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3715 {
3716   PetscFunctionBegin;
3717   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3718   PetscValidType(A, 1);
3719   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3720   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3721   PetscCheckSameComm(A, 1, B, 2);
3722   PetscCheckSameComm(A, 1, X, 3);
3723   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3724   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);
3725   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);
3726   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);
3727   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");
3728   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3729   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3730   MatCheckPreallocated(A, 1);
3731 
3732   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3733   if (!A->ops->matsolvetranspose) {
3734     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3735     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3736   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3737   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3738   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3739   PetscFunctionReturn(PETSC_SUCCESS);
3740 }
3741 
3742 /*@
3743    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3744 
3745    Neighbor-wise Collective on A
3746 
3747    Input Parameters:
3748 +  A - the factored matrix
3749 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3750 
3751    Output Parameter:
3752 .  X - the result matrix (dense matrix)
3753 
3754    Note:
3755    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
3756    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3757 
3758    Level: developer
3759 
3760 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3761 @*/
3762 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3763 {
3764   PetscFunctionBegin;
3765   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3766   PetscValidType(A, 1);
3767   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3768   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3769   PetscCheckSameComm(A, 1, Bt, 2);
3770   PetscCheckSameComm(A, 1, X, 3);
3771 
3772   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3773   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);
3774   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);
3775   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");
3776   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3777   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3778   MatCheckPreallocated(A, 1);
3779 
3780   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3781   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3782   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3783   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3784   PetscFunctionReturn(PETSC_SUCCESS);
3785 }
3786 
3787 /*@
3788    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3789                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3790 
3791    Neighbor-wise Collective
3792 
3793    Input Parameters:
3794 +  mat - the factored matrix
3795 -  b - the right-hand-side vector
3796 
3797    Output Parameter:
3798 .  x - the result vector
3799 
3800    Notes:
3801    `MatSolve()` should be used for most applications, as it performs
3802    a forward solve followed by a backward solve.
3803 
3804    The vectors b and x cannot be the same,  i.e., one cannot
3805    call `MatForwardSolve`(A,x,x).
3806 
3807    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3808    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3809    `MatForwardSolve()` solves U^T*D y = b, and
3810    `MatBackwardSolve()` solves U x = y.
3811    Thus they do not provide a symmetric preconditioner.
3812 
3813    Level: developer
3814 
3815 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3816 @*/
3817 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3818 {
3819   PetscFunctionBegin;
3820   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3821   PetscValidType(mat, 1);
3822   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3823   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3824   PetscCheckSameComm(mat, 1, b, 2);
3825   PetscCheckSameComm(mat, 1, x, 3);
3826   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3827   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);
3828   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);
3829   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);
3830   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3831   MatCheckPreallocated(mat, 1);
3832 
3833   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3834   PetscUseTypeMethod(mat, forwardsolve, b, x);
3835   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3836   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3837   PetscFunctionReturn(PETSC_SUCCESS);
3838 }
3839 
3840 /*@
3841    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3842                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3843 
3844    Neighbor-wise Collective
3845 
3846    Input Parameters:
3847 +  mat - the factored matrix
3848 -  b - the right-hand-side vector
3849 
3850    Output Parameter:
3851 .  x - the result vector
3852 
3853    Notes:
3854    `MatSolve()` should be used for most applications, as it performs
3855    a forward solve followed by a backward solve.
3856 
3857    The vectors b and x cannot be the same.  I.e., one cannot
3858    call `MatBackwardSolve`(A,x,x).
3859 
3860    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3861    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3862    `MatForwardSolve()` solves U^T*D y = b, and
3863    `MatBackwardSolve()` solves U x = y.
3864    Thus they do not provide a symmetric preconditioner.
3865 
3866    Level: developer
3867 
3868 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3869 @*/
3870 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3871 {
3872   PetscFunctionBegin;
3873   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3874   PetscValidType(mat, 1);
3875   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3876   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3877   PetscCheckSameComm(mat, 1, b, 2);
3878   PetscCheckSameComm(mat, 1, x, 3);
3879   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3880   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);
3881   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);
3882   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);
3883   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3884   MatCheckPreallocated(mat, 1);
3885 
3886   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3887   PetscUseTypeMethod(mat, backwardsolve, b, x);
3888   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3889   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3890   PetscFunctionReturn(PETSC_SUCCESS);
3891 }
3892 
3893 /*@
3894    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3895 
3896    Neighbor-wise Collective
3897 
3898    Input Parameters:
3899 +  mat - the factored matrix
3900 .  b - the right-hand-side vector
3901 -  y - the vector to be added to
3902 
3903    Output Parameter:
3904 .  x - the result vector
3905 
3906    Note:
3907    The vectors b and x cannot be the same.  I.e., one cannot
3908    call `MatSolveAdd`(A,x,y,x).
3909 
3910    Level: developer
3911 
3912 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3913 @*/
3914 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3915 {
3916   PetscScalar one = 1.0;
3917   Vec         tmp;
3918 
3919   PetscFunctionBegin;
3920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3921   PetscValidType(mat, 1);
3922   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3923   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3924   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3925   PetscCheckSameComm(mat, 1, b, 2);
3926   PetscCheckSameComm(mat, 1, y, 3);
3927   PetscCheckSameComm(mat, 1, x, 4);
3928   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3929   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);
3930   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);
3931   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);
3932   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);
3933   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);
3934   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3935   MatCheckPreallocated(mat, 1);
3936 
3937   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3938   if (mat->factorerrortype) {
3939     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3940     PetscCall(VecSetInf(x));
3941   } else if (mat->ops->solveadd) {
3942     PetscUseTypeMethod(mat, solveadd, b, y, x);
3943   } else {
3944     /* do the solve then the add manually */
3945     if (x != y) {
3946       PetscCall(MatSolve(mat, b, x));
3947       PetscCall(VecAXPY(x, one, y));
3948     } else {
3949       PetscCall(VecDuplicate(x, &tmp));
3950       PetscCall(VecCopy(x, tmp));
3951       PetscCall(MatSolve(mat, b, x));
3952       PetscCall(VecAXPY(x, one, tmp));
3953       PetscCall(VecDestroy(&tmp));
3954     }
3955   }
3956   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3957   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3958   PetscFunctionReturn(PETSC_SUCCESS);
3959 }
3960 
3961 /*@
3962    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3963 
3964    Neighbor-wise Collective
3965 
3966    Input Parameters:
3967 +  mat - the factored matrix
3968 -  b - the right-hand-side vector
3969 
3970    Output Parameter:
3971 .  x - the result vector
3972 
3973    Notes:
3974    The vectors b and x cannot be the same.  I.e., one cannot
3975    call `MatSolveTranspose`(A,x,x).
3976 
3977    Most users should employ the `KSP` interface for linear solvers
3978    instead of working directly with matrix algebra routines such as this.
3979    See, e.g., `KSPCreate()`.
3980 
3981    Level: developer
3982 
3983 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3984 @*/
3985 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3986 {
3987   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3988 
3989   PetscFunctionBegin;
3990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3991   PetscValidType(mat, 1);
3992   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3993   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3994   PetscCheckSameComm(mat, 1, b, 2);
3995   PetscCheckSameComm(mat, 1, x, 3);
3996   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3997   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);
3998   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);
3999   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4000   MatCheckPreallocated(mat, 1);
4001   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4002   if (mat->factorerrortype) {
4003     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4004     PetscCall(VecSetInf(x));
4005   } else {
4006     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4007     PetscCall((*f)(mat, b, x));
4008   }
4009   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4010   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4011   PetscFunctionReturn(PETSC_SUCCESS);
4012 }
4013 
4014 /*@
4015    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4016                       factored matrix.
4017 
4018    Neighbor-wise Collective
4019 
4020    Input Parameters:
4021 +  mat - the factored matrix
4022 .  b - the right-hand-side vector
4023 -  y - the vector to be added to
4024 
4025    Output Parameter:
4026 .  x - the result vector
4027 
4028    Note:
4029    The vectors b and x cannot be the same.  I.e., one cannot
4030    call `MatSolveTransposeAdd`(A,x,y,x).
4031 
4032    Level: developer
4033 
4034 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4035 @*/
4036 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4037 {
4038   PetscScalar one = 1.0;
4039   Vec         tmp;
4040   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4041 
4042   PetscFunctionBegin;
4043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4044   PetscValidType(mat, 1);
4045   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4046   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4047   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4048   PetscCheckSameComm(mat, 1, b, 2);
4049   PetscCheckSameComm(mat, 1, y, 3);
4050   PetscCheckSameComm(mat, 1, x, 4);
4051   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4052   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);
4053   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);
4054   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);
4055   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);
4056   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4057   MatCheckPreallocated(mat, 1);
4058 
4059   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4060   if (mat->factorerrortype) {
4061     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4062     PetscCall(VecSetInf(x));
4063   } else if (f) {
4064     PetscCall((*f)(mat, b, y, x));
4065   } else {
4066     /* do the solve then the add manually */
4067     if (x != y) {
4068       PetscCall(MatSolveTranspose(mat, b, x));
4069       PetscCall(VecAXPY(x, one, y));
4070     } else {
4071       PetscCall(VecDuplicate(x, &tmp));
4072       PetscCall(VecCopy(x, tmp));
4073       PetscCall(MatSolveTranspose(mat, b, x));
4074       PetscCall(VecAXPY(x, one, tmp));
4075       PetscCall(VecDestroy(&tmp));
4076     }
4077   }
4078   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4079   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4080   PetscFunctionReturn(PETSC_SUCCESS);
4081 }
4082 /* ----------------------------------------------------------------*/
4083 
4084 /*@
4085    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4086 
4087    Neighbor-wise Collective
4088 
4089    Input Parameters:
4090 +  mat - the matrix
4091 .  b - the right hand side
4092 .  omega - the relaxation factor
4093 .  flag - flag indicating the type of SOR (see below)
4094 .  shift -  diagonal shift
4095 .  its - the number of iterations
4096 -  lits - the number of local iterations
4097 
4098    Output Parameter:
4099 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4100 
4101    SOR Flags:
4102 +     `SOR_FORWARD_SWEEP` - forward SOR
4103 .     `SOR_BACKWARD_SWEEP` - backward SOR
4104 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4105 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4106 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4107 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4108 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4109 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4110          upper/lower triangular part of matrix to
4111          vector (with omega)
4112 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4113 
4114    Notes:
4115    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4116    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4117    on each processor.
4118 
4119    Application programmers will not generally use `MatSOR()` directly,
4120    but instead will employ the `KSP`/`PC` interface.
4121 
4122    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4123 
4124    Most users should employ the `KSP` interface for linear solvers
4125    instead of working directly with matrix algebra routines such as this.
4126    See, e.g., `KSPCreate()`.
4127 
4128    Vectors x and b CANNOT be the same
4129 
4130    Notes for Advanced Users:
4131    The flags are implemented as bitwise inclusive or operations.
4132    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4133    to specify a zero initial guess for SSOR.
4134 
4135    Developer Note:
4136    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4137 
4138    Level: developer
4139 
4140 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4141 @*/
4142 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4143 {
4144   PetscFunctionBegin;
4145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4146   PetscValidType(mat, 1);
4147   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4148   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4149   PetscCheckSameComm(mat, 1, b, 2);
4150   PetscCheckSameComm(mat, 1, x, 8);
4151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4153   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);
4154   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);
4155   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);
4156   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4157   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4158   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4159 
4160   MatCheckPreallocated(mat, 1);
4161   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4162   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4163   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4164   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4165   PetscFunctionReturn(PETSC_SUCCESS);
4166 }
4167 
4168 /*
4169       Default matrix copy routine.
4170 */
4171 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4172 {
4173   PetscInt           i, rstart = 0, rend = 0, nz;
4174   const PetscInt    *cwork;
4175   const PetscScalar *vwork;
4176 
4177   PetscFunctionBegin;
4178   if (B->assembled) PetscCall(MatZeroEntries(B));
4179   if (str == SAME_NONZERO_PATTERN) {
4180     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4181     for (i = rstart; i < rend; i++) {
4182       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4183       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4184       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4185     }
4186   } else {
4187     PetscCall(MatAYPX(B, 0.0, A, str));
4188   }
4189   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4190   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4191   PetscFunctionReturn(PETSC_SUCCESS);
4192 }
4193 
4194 /*@
4195    MatCopy - Copies a matrix to another matrix.
4196 
4197    Collective on A
4198 
4199    Input Parameters:
4200 +  A - the matrix
4201 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4202 
4203    Output Parameter:
4204 .  B - where the copy is put
4205 
4206    Notes:
4207    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4208 
4209    `MatCopy()` copies the matrix entries of a matrix to another existing
4210    matrix (after first zeroing the second matrix).  A related routine is
4211    `MatConvert()`, which first creates a new matrix and then copies the data.
4212 
4213    Level: intermediate
4214 
4215 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4216 @*/
4217 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4218 {
4219   PetscInt i;
4220 
4221   PetscFunctionBegin;
4222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4223   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4224   PetscValidType(A, 1);
4225   PetscValidType(B, 2);
4226   PetscCheckSameComm(A, 1, B, 2);
4227   MatCheckPreallocated(B, 2);
4228   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4229   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4230   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,
4231              A->cmap->N, B->cmap->N);
4232   MatCheckPreallocated(A, 1);
4233   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4234 
4235   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4236   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4237   else PetscCall(MatCopy_Basic(A, B, str));
4238 
4239   B->stencil.dim = A->stencil.dim;
4240   B->stencil.noc = A->stencil.noc;
4241   for (i = 0; i <= A->stencil.dim; i++) {
4242     B->stencil.dims[i]   = A->stencil.dims[i];
4243     B->stencil.starts[i] = A->stencil.starts[i];
4244   }
4245 
4246   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4247   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4248   PetscFunctionReturn(PETSC_SUCCESS);
4249 }
4250 
4251 /*@C
4252    MatConvert - Converts a matrix to another matrix, either of the same
4253    or different type.
4254 
4255    Collective
4256 
4257    Input Parameters:
4258 +  mat - the matrix
4259 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4260    same type as the original matrix.
4261 -  reuse - denotes if the destination matrix is to be created or reused.
4262    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
4263    `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).
4264 
4265    Output Parameter:
4266 .  M - pointer to place new matrix
4267 
4268    Notes:
4269    `MatConvert()` first creates a new matrix and then copies the data from
4270    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4271    entries of one matrix to another already existing matrix context.
4272 
4273    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4274    the MPI communicator of the generated matrix is always the same as the communicator
4275    of the input matrix.
4276 
4277    Level: intermediate
4278 
4279 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4280 @*/
4281 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4282 {
4283   PetscBool  sametype, issame, flg;
4284   PetscBool3 issymmetric, ishermitian;
4285   char       convname[256], mtype[256];
4286   Mat        B;
4287 
4288   PetscFunctionBegin;
4289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4290   PetscValidType(mat, 1);
4291   PetscValidPointer(M, 4);
4292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4294   MatCheckPreallocated(mat, 1);
4295 
4296   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4297   if (flg) newtype = mtype;
4298 
4299   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4300   PetscCall(PetscStrcmp(newtype, "same", &issame));
4301   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4302   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");
4303 
4304   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4305     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4306     PetscFunctionReturn(PETSC_SUCCESS);
4307   }
4308 
4309   /* Cache Mat options because some converters use MatHeaderReplace  */
4310   issymmetric = mat->symmetric;
4311   ishermitian = mat->hermitian;
4312 
4313   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4314     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4315     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4316   } else {
4317     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4318     const char *prefix[3]                                 = {"seq", "mpi", ""};
4319     PetscInt    i;
4320     /*
4321        Order of precedence:
4322        0) See if newtype is a superclass of the current matrix.
4323        1) See if a specialized converter is known to the current matrix.
4324        2) See if a specialized converter is known to the desired matrix class.
4325        3) See if a good general converter is registered for the desired class
4326           (as of 6/27/03 only MATMPIADJ falls into this category).
4327        4) See if a good general converter is known for the current matrix.
4328        5) Use a really basic converter.
4329     */
4330 
4331     /* 0) See if newtype is a superclass of the current matrix.
4332           i.e mat is mpiaij and newtype is aij */
4333     for (i = 0; i < 2; i++) {
4334       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4335       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4336       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4337       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4338       if (flg) {
4339         if (reuse == MAT_INPLACE_MATRIX) {
4340           PetscCall(PetscInfo(mat, "Early return\n"));
4341           PetscFunctionReturn(PETSC_SUCCESS);
4342         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4343           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4344           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345           PetscFunctionReturn(PETSC_SUCCESS);
4346         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4347           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4348           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4349           PetscFunctionReturn(PETSC_SUCCESS);
4350         }
4351       }
4352     }
4353     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4354     for (i = 0; i < 3; i++) {
4355       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4356       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4357       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4358       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4361       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4362       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4363       if (conv) goto foundconv;
4364     }
4365 
4366     /* 2)  See if a specialized converter is known to the desired matrix class. */
4367     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4368     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4369     PetscCall(MatSetType(B, newtype));
4370     for (i = 0; i < 3; i++) {
4371       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4372       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4377       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4378       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4379       if (conv) {
4380         PetscCall(MatDestroy(&B));
4381         goto foundconv;
4382       }
4383     }
4384 
4385     /* 3) See if a good general converter is registered for the desired class */
4386     conv = B->ops->convertfrom;
4387     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4388     PetscCall(MatDestroy(&B));
4389     if (conv) goto foundconv;
4390 
4391     /* 4) See if a good general converter is known for the current matrix */
4392     if (mat->ops->convert) conv = mat->ops->convert;
4393     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4394     if (conv) goto foundconv;
4395 
4396     /* 5) Use a really basic converter. */
4397     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4398     conv = MatConvert_Basic;
4399 
4400   foundconv:
4401     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4402     PetscCall((*conv)(mat, newtype, reuse, M));
4403     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4404       /* the block sizes must be same if the mappings are copied over */
4405       (*M)->rmap->bs = mat->rmap->bs;
4406       (*M)->cmap->bs = mat->cmap->bs;
4407       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4408       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4409       (*M)->rmap->mapping = mat->rmap->mapping;
4410       (*M)->cmap->mapping = mat->cmap->mapping;
4411     }
4412     (*M)->stencil.dim = mat->stencil.dim;
4413     (*M)->stencil.noc = mat->stencil.noc;
4414     for (i = 0; i <= mat->stencil.dim; i++) {
4415       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4416       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4417     }
4418     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4419   }
4420   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4421 
4422   /* Copy Mat options */
4423   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4424   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4425   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4426   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4427   PetscFunctionReturn(PETSC_SUCCESS);
4428 }
4429 
4430 /*@C
4431    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4432 
4433    Not Collective
4434 
4435    Input Parameter:
4436 .  mat - the matrix, must be a factored matrix
4437 
4438    Output Parameter:
4439 .   type - the string name of the package (do not free this string)
4440 
4441    Level: intermediate
4442 
4443    Note:
4444       In Fortran you pass in a empty string and the package name will be copied into it.
4445     (Make sure the string is long enough)
4446 
4447 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4448 @*/
4449 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4450 {
4451   PetscErrorCode (*conv)(Mat, MatSolverType *);
4452 
4453   PetscFunctionBegin;
4454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4455   PetscValidType(mat, 1);
4456   PetscValidPointer(type, 2);
4457   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4458   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4459   if (conv) PetscCall((*conv)(mat, type));
4460   else *type = MATSOLVERPETSC;
4461   PetscFunctionReturn(PETSC_SUCCESS);
4462 }
4463 
4464 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4465 struct _MatSolverTypeForSpecifcType {
4466   MatType mtype;
4467   /* no entry for MAT_FACTOR_NONE */
4468   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4469   MatSolverTypeForSpecifcType next;
4470 };
4471 
4472 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4473 struct _MatSolverTypeHolder {
4474   char                       *name;
4475   MatSolverTypeForSpecifcType handlers;
4476   MatSolverTypeHolder         next;
4477 };
4478 
4479 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4480 
4481 /*@C
4482    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4483 
4484    Input Parameters:
4485 +    package - name of the package, for example petsc or superlu
4486 .    mtype - the matrix type that works with this package
4487 .    ftype - the type of factorization supported by the package
4488 -    createfactor - routine that will create the factored matrix ready to be used
4489 
4490     Level: developer
4491 
4492 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4493 @*/
4494 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4495 {
4496   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4497   PetscBool                   flg;
4498   MatSolverTypeForSpecifcType inext, iprev = NULL;
4499 
4500   PetscFunctionBegin;
4501   PetscCall(MatInitializePackage());
4502   if (!next) {
4503     PetscCall(PetscNew(&MatSolverTypeHolders));
4504     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4505     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4506     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4507     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4508     PetscFunctionReturn(PETSC_SUCCESS);
4509   }
4510   while (next) {
4511     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4512     if (flg) {
4513       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4514       inext = next->handlers;
4515       while (inext) {
4516         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4517         if (flg) {
4518           inext->createfactor[(int)ftype - 1] = createfactor;
4519           PetscFunctionReturn(PETSC_SUCCESS);
4520         }
4521         iprev = inext;
4522         inext = inext->next;
4523       }
4524       PetscCall(PetscNew(&iprev->next));
4525       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4526       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4527       PetscFunctionReturn(PETSC_SUCCESS);
4528     }
4529     prev = next;
4530     next = next->next;
4531   }
4532   PetscCall(PetscNew(&prev->next));
4533   PetscCall(PetscStrallocpy(package, &prev->next->name));
4534   PetscCall(PetscNew(&prev->next->handlers));
4535   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4536   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4537   PetscFunctionReturn(PETSC_SUCCESS);
4538 }
4539 
4540 /*@C
4541    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4542 
4543    Input Parameters:
4544 +    type - name of the package, for example petsc or superlu
4545 .    ftype - the type of factorization supported by the type
4546 -    mtype - the matrix type that works with this type
4547 
4548    Output Parameters:
4549 +   foundtype - `PETSC_TRUE` if the type was registered
4550 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4551 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4552 
4553     Level: developer
4554 
4555 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4556 @*/
4557 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4558 {
4559   MatSolverTypeHolder         next = MatSolverTypeHolders;
4560   PetscBool                   flg;
4561   MatSolverTypeForSpecifcType inext;
4562 
4563   PetscFunctionBegin;
4564   if (foundtype) *foundtype = PETSC_FALSE;
4565   if (foundmtype) *foundmtype = PETSC_FALSE;
4566   if (createfactor) *createfactor = NULL;
4567 
4568   if (type) {
4569     while (next) {
4570       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4571       if (flg) {
4572         if (foundtype) *foundtype = PETSC_TRUE;
4573         inext = next->handlers;
4574         while (inext) {
4575           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4576           if (flg) {
4577             if (foundmtype) *foundmtype = PETSC_TRUE;
4578             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4579             PetscFunctionReturn(PETSC_SUCCESS);
4580           }
4581           inext = inext->next;
4582         }
4583       }
4584       next = next->next;
4585     }
4586   } else {
4587     while (next) {
4588       inext = next->handlers;
4589       while (inext) {
4590         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4591         if (flg && inext->createfactor[(int)ftype - 1]) {
4592           if (foundtype) *foundtype = PETSC_TRUE;
4593           if (foundmtype) *foundmtype = PETSC_TRUE;
4594           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4595           PetscFunctionReturn(PETSC_SUCCESS);
4596         }
4597         inext = inext->next;
4598       }
4599       next = next->next;
4600     }
4601     /* try with base classes inext->mtype */
4602     next = MatSolverTypeHolders;
4603     while (next) {
4604       inext = next->handlers;
4605       while (inext) {
4606         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4607         if (flg && inext->createfactor[(int)ftype - 1]) {
4608           if (foundtype) *foundtype = PETSC_TRUE;
4609           if (foundmtype) *foundmtype = PETSC_TRUE;
4610           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4611           PetscFunctionReturn(PETSC_SUCCESS);
4612         }
4613         inext = inext->next;
4614       }
4615       next = next->next;
4616     }
4617   }
4618   PetscFunctionReturn(PETSC_SUCCESS);
4619 }
4620 
4621 PetscErrorCode MatSolverTypeDestroy(void)
4622 {
4623   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4624   MatSolverTypeForSpecifcType inext, iprev;
4625 
4626   PetscFunctionBegin;
4627   while (next) {
4628     PetscCall(PetscFree(next->name));
4629     inext = next->handlers;
4630     while (inext) {
4631       PetscCall(PetscFree(inext->mtype));
4632       iprev = inext;
4633       inext = inext->next;
4634       PetscCall(PetscFree(iprev));
4635     }
4636     prev = next;
4637     next = next->next;
4638     PetscCall(PetscFree(prev));
4639   }
4640   MatSolverTypeHolders = NULL;
4641   PetscFunctionReturn(PETSC_SUCCESS);
4642 }
4643 
4644 /*@C
4645    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4646 
4647    Logically Collective
4648 
4649    Input Parameters:
4650 .  mat - the matrix
4651 
4652    Output Parameters:
4653 .  flg - `PETSC_TRUE` if uses the ordering
4654 
4655    Note:
4656    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4657    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4658 
4659    Level: developer
4660 
4661 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4662 @*/
4663 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4664 {
4665   PetscFunctionBegin;
4666   *flg = mat->canuseordering;
4667   PetscFunctionReturn(PETSC_SUCCESS);
4668 }
4669 
4670 /*@C
4671    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4672 
4673    Logically Collective
4674 
4675    Input Parameters:
4676 .  mat - the matrix obtained with `MatGetFactor()`
4677 
4678    Output Parameters:
4679 .  otype - the preferred type
4680 
4681    Level: developer
4682 
4683 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4684 @*/
4685 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4686 {
4687   PetscFunctionBegin;
4688   *otype = mat->preferredordering[ftype];
4689   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4690   PetscFunctionReturn(PETSC_SUCCESS);
4691 }
4692 
4693 /*@C
4694    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4695 
4696    Collective
4697 
4698    Input Parameters:
4699 +  mat - the matrix
4700 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4701 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4702 
4703    Output Parameters:
4704 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4705 
4706    Options Database Key:
4707 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4708                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4709 
4710    Notes:
4711      Users usually access the factorization solvers via `KSP`
4712 
4713       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4714      such as pastix, superlu, mumps etc.
4715 
4716       PETSc must have been ./configure to use the external solver, using the option --download-package
4717 
4718       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4719       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4720       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4721 
4722    Developer Note:
4723       This should actually be called `MatCreateFactor()` since it creates a new factor object
4724 
4725    Level: intermediate
4726 
4727 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4728           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4729 @*/
4730 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4731 {
4732   PetscBool foundtype, foundmtype;
4733   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4734 
4735   PetscFunctionBegin;
4736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4737   PetscValidType(mat, 1);
4738 
4739   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4740   MatCheckPreallocated(mat, 1);
4741 
4742   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4743   if (!foundtype) {
4744     if (type) {
4745       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],
4746               ((PetscObject)mat)->type_name, type);
4747     } else {
4748       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);
4749     }
4750   }
4751   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4752   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);
4753 
4754   PetscCall((*conv)(mat, ftype, f));
4755   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4756   PetscFunctionReturn(PETSC_SUCCESS);
4757 }
4758 
4759 /*@C
4760    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4761 
4762    Not Collective
4763 
4764    Input Parameters:
4765 +  mat - the matrix
4766 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4767 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4768 
4769    Output Parameter:
4770 .    flg - PETSC_TRUE if the factorization is available
4771 
4772    Notes:
4773       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4774      such as pastix, superlu, mumps etc.
4775 
4776       PETSc must have been ./configure to use the external solver, using the option --download-package
4777 
4778    Developer Note:
4779       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4780 
4781    Level: intermediate
4782 
4783 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4784           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4785 @*/
4786 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4787 {
4788   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4789 
4790   PetscFunctionBegin;
4791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4792   PetscValidType(mat, 1);
4793   PetscValidBoolPointer(flg, 4);
4794 
4795   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4796   MatCheckPreallocated(mat, 1);
4797 
4798   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4799   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4800   PetscFunctionReturn(PETSC_SUCCESS);
4801 }
4802 
4803 /*@
4804    MatDuplicate - Duplicates a matrix including the non-zero structure.
4805 
4806    Collective
4807 
4808    Input Parameters:
4809 +  mat - the matrix
4810 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4811         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4812 
4813    Output Parameter:
4814 .  M - pointer to place new matrix
4815 
4816    Level: intermediate
4817 
4818    Notes:
4819     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4820 
4821     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.
4822 
4823     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
4824     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4825     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4826 
4827 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4828 @*/
4829 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4830 {
4831   Mat         B;
4832   VecType     vtype;
4833   PetscInt    i;
4834   PetscObject dm;
4835   void (*viewf)(void);
4836 
4837   PetscFunctionBegin;
4838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4839   PetscValidType(mat, 1);
4840   PetscValidPointer(M, 3);
4841   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4842   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4843   MatCheckPreallocated(mat, 1);
4844 
4845   *M = NULL;
4846   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4847   PetscUseTypeMethod(mat, duplicate, op, M);
4848   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4849   B = *M;
4850 
4851   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4852   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4853   PetscCall(MatGetVecType(mat, &vtype));
4854   PetscCall(MatSetVecType(B, vtype));
4855 
4856   B->stencil.dim = mat->stencil.dim;
4857   B->stencil.noc = mat->stencil.noc;
4858   for (i = 0; i <= mat->stencil.dim; i++) {
4859     B->stencil.dims[i]   = mat->stencil.dims[i];
4860     B->stencil.starts[i] = mat->stencil.starts[i];
4861   }
4862 
4863   B->nooffproczerorows = mat->nooffproczerorows;
4864   B->nooffprocentries  = mat->nooffprocentries;
4865 
4866   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4867   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4868   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4869   PetscFunctionReturn(PETSC_SUCCESS);
4870 }
4871 
4872 /*@
4873    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4874 
4875    Logically Collective
4876 
4877    Input Parameters:
4878 +  mat - the matrix
4879 -  v - the vector for storing the diagonal
4880 
4881    Output Parameter:
4882 .  v - the diagonal of the matrix
4883 
4884    Level: intermediate
4885 
4886    Note:
4887    Currently only correct in parallel for square matrices.
4888 
4889 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4890 @*/
4891 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4892 {
4893   PetscFunctionBegin;
4894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4895   PetscValidType(mat, 1);
4896   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4897   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4898   MatCheckPreallocated(mat, 1);
4899 
4900   PetscUseTypeMethod(mat, getdiagonal, v);
4901   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4902   PetscFunctionReturn(PETSC_SUCCESS);
4903 }
4904 
4905 /*@C
4906    MatGetRowMin - Gets the minimum value (of the real part) of each
4907         row of the matrix
4908 
4909    Logically Collective
4910 
4911    Input Parameter:
4912 .  mat - the matrix
4913 
4914    Output Parameters:
4915 +  v - the vector for storing the maximums
4916 -  idx - the indices of the column found for each row (optional)
4917 
4918    Level: intermediate
4919 
4920    Note:
4921     The result of this call are the same as if one converted the matrix to dense format
4922       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4923 
4924     This code is only implemented for a couple of matrix formats.
4925 
4926 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4927           `MatGetRowMax()`
4928 @*/
4929 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4930 {
4931   PetscFunctionBegin;
4932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4933   PetscValidType(mat, 1);
4934   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4935   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4936 
4937   if (!mat->cmap->N) {
4938     PetscCall(VecSet(v, PETSC_MAX_REAL));
4939     if (idx) {
4940       PetscInt i, m = mat->rmap->n;
4941       for (i = 0; i < m; i++) idx[i] = -1;
4942     }
4943   } else {
4944     MatCheckPreallocated(mat, 1);
4945   }
4946   PetscUseTypeMethod(mat, getrowmin, v, idx);
4947   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4948   PetscFunctionReturn(PETSC_SUCCESS);
4949 }
4950 
4951 /*@C
4952    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4953         row of the matrix
4954 
4955    Logically Collective
4956 
4957    Input Parameter:
4958 .  mat - the matrix
4959 
4960    Output Parameters:
4961 +  v - the vector for storing the minimums
4962 -  idx - the indices of the column found for each row (or NULL if not needed)
4963 
4964    Level: intermediate
4965 
4966    Notes:
4967     if a row is completely empty or has only 0.0 values then the idx[] value for that
4968     row is 0 (the first column).
4969 
4970     This code is only implemented for a couple of matrix formats.
4971 
4972 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4973 @*/
4974 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4975 {
4976   PetscFunctionBegin;
4977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4978   PetscValidType(mat, 1);
4979   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4980   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4981   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4982 
4983   if (!mat->cmap->N) {
4984     PetscCall(VecSet(v, 0.0));
4985     if (idx) {
4986       PetscInt i, m = mat->rmap->n;
4987       for (i = 0; i < m; i++) idx[i] = -1;
4988     }
4989   } else {
4990     MatCheckPreallocated(mat, 1);
4991     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4992     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4993   }
4994   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4995   PetscFunctionReturn(PETSC_SUCCESS);
4996 }
4997 
4998 /*@C
4999    MatGetRowMax - Gets the maximum value (of the real part) of each
5000         row of the matrix
5001 
5002    Logically Collective
5003 
5004    Input Parameter:
5005 .  mat - the matrix
5006 
5007    Output Parameters:
5008 +  v - the vector for storing the maximums
5009 -  idx - the indices of the column found for each row (optional)
5010 
5011    Level: intermediate
5012 
5013    Notes:
5014     The result of this call are the same as if one converted the matrix to dense format
5015       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5016 
5017     This code is only implemented for a couple of matrix formats.
5018 
5019 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5020 @*/
5021 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5022 {
5023   PetscFunctionBegin;
5024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5025   PetscValidType(mat, 1);
5026   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5027   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5028 
5029   if (!mat->cmap->N) {
5030     PetscCall(VecSet(v, PETSC_MIN_REAL));
5031     if (idx) {
5032       PetscInt i, m = mat->rmap->n;
5033       for (i = 0; i < m; i++) idx[i] = -1;
5034     }
5035   } else {
5036     MatCheckPreallocated(mat, 1);
5037     PetscUseTypeMethod(mat, getrowmax, v, idx);
5038   }
5039   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5040   PetscFunctionReturn(PETSC_SUCCESS);
5041 }
5042 
5043 /*@C
5044    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5045         row of the matrix
5046 
5047    Logically Collective
5048 
5049    Input Parameter:
5050 .  mat - the matrix
5051 
5052    Output Parameters:
5053 +  v - the vector for storing the maximums
5054 -  idx - the indices of the column found for each row (or NULL if not needed)
5055 
5056    Level: intermediate
5057 
5058    Notes:
5059     if a row is completely empty or has only 0.0 values then the idx[] value for that
5060     row is 0 (the first column).
5061 
5062     This code is only implemented for a couple of matrix formats.
5063 
5064 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5065 @*/
5066 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5067 {
5068   PetscFunctionBegin;
5069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5070   PetscValidType(mat, 1);
5071   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5072   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5073 
5074   if (!mat->cmap->N) {
5075     PetscCall(VecSet(v, 0.0));
5076     if (idx) {
5077       PetscInt i, m = mat->rmap->n;
5078       for (i = 0; i < m; i++) idx[i] = -1;
5079     }
5080   } else {
5081     MatCheckPreallocated(mat, 1);
5082     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5083     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5084   }
5085   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5086   PetscFunctionReturn(PETSC_SUCCESS);
5087 }
5088 
5089 /*@
5090    MatGetRowSum - Gets the sum of each row of the matrix
5091 
5092    Logically or Neighborhood Collective
5093 
5094    Input Parameters:
5095 .  mat - the matrix
5096 
5097    Output Parameter:
5098 .  v - the vector for storing the sum of rows
5099 
5100    Level: intermediate
5101 
5102    Notes:
5103     This code is slow since it is not currently specialized for different formats
5104 
5105 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5106 @*/
5107 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5108 {
5109   Vec ones;
5110 
5111   PetscFunctionBegin;
5112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5113   PetscValidType(mat, 1);
5114   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5115   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5116   MatCheckPreallocated(mat, 1);
5117   PetscCall(MatCreateVecs(mat, &ones, NULL));
5118   PetscCall(VecSet(ones, 1.));
5119   PetscCall(MatMult(mat, ones, v));
5120   PetscCall(VecDestroy(&ones));
5121   PetscFunctionReturn(PETSC_SUCCESS);
5122 }
5123 
5124 /*@
5125    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5126    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5127 
5128    Collective
5129 
5130    Input Parameter:
5131 .  mat - the matrix to provide the transpose
5132 
5133    Output Parameter:
5134 .  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
5135 
5136    Level: advanced
5137 
5138    Note:
5139    Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5140    routine allows bypassing that call.
5141 
5142 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5143 @*/
5144 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5145 {
5146   PetscContainer  rB = NULL;
5147   MatParentState *rb = NULL;
5148 
5149   PetscFunctionBegin;
5150   PetscCall(PetscNew(&rb));
5151   rb->id    = ((PetscObject)mat)->id;
5152   rb->state = 0;
5153   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5154   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5155   PetscCall(PetscContainerSetPointer(rB, rb));
5156   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5157   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5158   PetscCall(PetscObjectDereference((PetscObject)rB));
5159   PetscFunctionReturn(PETSC_SUCCESS);
5160 }
5161 
5162 /*@
5163    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5164 
5165    Collective
5166 
5167    Input Parameters:
5168 +  mat - the matrix to transpose
5169 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5170 
5171    Output Parameter:
5172 .  B - the transpose
5173 
5174    Notes:
5175      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5176 
5177      `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5178      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5179 
5180      If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types.
5181 
5182      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5183 
5184      If mat is unchanged from the last call this function returns immediately without recomputing the result
5185 
5186      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5187 
5188    Level: intermediate
5189 
5190 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5191           `MatTransposeSymbolic()`
5192 @*/
5193 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5194 {
5195   PetscContainer  rB = NULL;
5196   MatParentState *rb = NULL;
5197 
5198   PetscFunctionBegin;
5199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5200   PetscValidType(mat, 1);
5201   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5202   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5203   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5204   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5205   MatCheckPreallocated(mat, 1);
5206   if (reuse == MAT_REUSE_MATRIX) {
5207     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5208     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5209     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5210     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5211     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5212   }
5213 
5214   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5215   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5216     PetscUseTypeMethod(mat, transpose, reuse, B);
5217     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5218   }
5219   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5220 
5221   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5222   if (reuse != MAT_INPLACE_MATRIX) {
5223     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5224     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5225     rb->state        = ((PetscObject)mat)->state;
5226     rb->nonzerostate = mat->nonzerostate;
5227   }
5228   PetscFunctionReturn(PETSC_SUCCESS);
5229 }
5230 
5231 /*@
5232    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5233 
5234    Collective on A
5235 
5236    Input Parameters:
5237 .  A - the matrix to transpose
5238 
5239    Output Parameter:
5240 .  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
5241       numerical portion.
5242 
5243    Level: intermediate
5244 
5245    Note:
5246    This is not supported for many matrix types, use `MatTranspose()` in those cases
5247 
5248 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5249 @*/
5250 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5251 {
5252   PetscFunctionBegin;
5253   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5254   PetscValidType(A, 1);
5255   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5256   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5257   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5258   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5259   PetscCall((*A->ops->transposesymbolic)(A, B));
5260   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5261 
5262   PetscCall(MatTransposeSetPrecursor(A, *B));
5263   PetscFunctionReturn(PETSC_SUCCESS);
5264 }
5265 
5266 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5267 {
5268   PetscContainer  rB;
5269   MatParentState *rb;
5270 
5271   PetscFunctionBegin;
5272   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5273   PetscValidType(A, 1);
5274   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5275   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5276   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5277   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5278   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5279   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5280   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5281   PetscFunctionReturn(PETSC_SUCCESS);
5282 }
5283 
5284 /*@
5285    MatIsTranspose - Test whether a matrix is another one's transpose,
5286         or its own, in which case it tests symmetry.
5287 
5288    Collective on A
5289 
5290    Input Parameters:
5291 +  A - the matrix to test
5292 -  B - the matrix to test against, this can equal the first parameter
5293 
5294    Output Parameters:
5295 .  flg - the result
5296 
5297    Notes:
5298    Only available for `MATAIJ` matrices.
5299 
5300    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5301    test involves parallel copies of the block-offdiagonal parts of the matrix.
5302 
5303    Level: intermediate
5304 
5305 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5306 @*/
5307 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5308 {
5309   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5310 
5311   PetscFunctionBegin;
5312   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5313   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5314   PetscValidBoolPointer(flg, 4);
5315   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5316   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5317   *flg = PETSC_FALSE;
5318   if (f && g) {
5319     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5320     PetscCall((*f)(A, B, tol, flg));
5321   } else {
5322     MatType mattype;
5323 
5324     PetscCall(MatGetType(f ? B : A, &mattype));
5325     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5326   }
5327   PetscFunctionReturn(PETSC_SUCCESS);
5328 }
5329 
5330 /*@
5331    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5332 
5333    Collective
5334 
5335    Input Parameters:
5336 +  mat - the matrix to transpose and complex conjugate
5337 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5338 
5339    Output Parameter:
5340 .  B - the Hermitian transpose
5341 
5342    Level: intermediate
5343 
5344 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5345 @*/
5346 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5347 {
5348   PetscFunctionBegin;
5349   PetscCall(MatTranspose(mat, reuse, B));
5350 #if defined(PETSC_USE_COMPLEX)
5351   PetscCall(MatConjugate(*B));
5352 #endif
5353   PetscFunctionReturn(PETSC_SUCCESS);
5354 }
5355 
5356 /*@
5357    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5358 
5359    Collective on A
5360 
5361    Input Parameters:
5362 +  A - the matrix to test
5363 -  B - the matrix to test against, this can equal the first parameter
5364 
5365    Output Parameters:
5366 .  flg - the result
5367 
5368    Notes:
5369    Only available for `MATAIJ` matrices.
5370 
5371    The sequential algorithm
5372    has a running time of the order of the number of nonzeros; the parallel
5373    test involves parallel copies of the block-offdiagonal parts of the matrix.
5374 
5375    Level: intermediate
5376 
5377 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5378 @*/
5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5380 {
5381   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5382 
5383   PetscFunctionBegin;
5384   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5385   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5386   PetscValidBoolPointer(flg, 4);
5387   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5388   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5389   if (f && g) {
5390     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5391     PetscCall((*f)(A, B, tol, flg));
5392   }
5393   PetscFunctionReturn(PETSC_SUCCESS);
5394 }
5395 
5396 /*@
5397    MatPermute - Creates a new matrix with rows and columns permuted from the
5398    original.
5399 
5400    Collective
5401 
5402    Input Parameters:
5403 +  mat - the matrix to permute
5404 .  row - row permutation, each processor supplies only the permutation for its rows
5405 -  col - column permutation, each processor supplies only the permutation for its columns
5406 
5407    Output Parameters:
5408 .  B - the permuted matrix
5409 
5410    Level: advanced
5411 
5412    Note:
5413    The index sets map from row/col of permuted matrix to row/col of original matrix.
5414    The index sets should be on the same communicator as mat and have the same local sizes.
5415 
5416    Developer Note:
5417      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5418      exploit the fact that row and col are permutations, consider implementing the
5419      more general `MatCreateSubMatrix()` instead.
5420 
5421 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5422 @*/
5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5424 {
5425   PetscFunctionBegin;
5426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5427   PetscValidType(mat, 1);
5428   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5429   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5430   PetscValidPointer(B, 4);
5431   PetscCheckSameComm(mat, 1, row, 2);
5432   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5435   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5436   MatCheckPreallocated(mat, 1);
5437 
5438   if (mat->ops->permute) {
5439     PetscUseTypeMethod(mat, permute, row, col, B);
5440     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5441   } else {
5442     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5443   }
5444   PetscFunctionReturn(PETSC_SUCCESS);
5445 }
5446 
5447 /*@
5448    MatEqual - Compares two matrices.
5449 
5450    Collective on A
5451 
5452    Input Parameters:
5453 +  A - the first matrix
5454 -  B - the second matrix
5455 
5456    Output Parameter:
5457 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5458 
5459    Level: intermediate
5460 
5461 .seealso: `Mat`
5462 @*/
5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5464 {
5465   PetscFunctionBegin;
5466   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5467   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5468   PetscValidType(A, 1);
5469   PetscValidType(B, 2);
5470   PetscValidBoolPointer(flg, 3);
5471   PetscCheckSameComm(A, 1, B, 2);
5472   MatCheckPreallocated(A, 1);
5473   MatCheckPreallocated(B, 2);
5474   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5476   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5477              B->cmap->N);
5478   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5479     PetscUseTypeMethod(A, equal, B, flg);
5480   } else {
5481     PetscCall(MatMultEqual(A, B, 10, flg));
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5488    matrices that are stored as vectors.  Either of the two scaling
5489    matrices can be NULL.
5490 
5491    Collective
5492 
5493    Input Parameters:
5494 +  mat - the matrix to be scaled
5495 .  l - the left scaling vector (or NULL)
5496 -  r - the right scaling vector (or NULL)
5497 
5498    Note:
5499    `MatDiagonalScale()` computes A = LAR, where
5500    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5501    The L scales the rows of the matrix, the R scales the columns of the matrix.
5502 
5503    Level: intermediate
5504 
5505 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5506 @*/
5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5511   PetscValidType(mat, 1);
5512   if (l) {
5513     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5514     PetscCheckSameComm(mat, 1, l, 2);
5515   }
5516   if (r) {
5517     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5518     PetscCheckSameComm(mat, 1, r, 3);
5519   }
5520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5522   MatCheckPreallocated(mat, 1);
5523   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5524 
5525   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5526   PetscUseTypeMethod(mat, diagonalscale, l, r);
5527   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5528   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5529   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5530   PetscFunctionReturn(PETSC_SUCCESS);
5531 }
5532 
5533 /*@
5534     MatScale - Scales all elements of a matrix by a given number.
5535 
5536     Logically Collective
5537 
5538     Input Parameters:
5539 +   mat - the matrix to be scaled
5540 -   a  - the scaling value
5541 
5542     Output Parameter:
5543 .   mat - the scaled matrix
5544 
5545     Level: intermediate
5546 
5547 .seealso: `Mat`, `MatDiagonalScale()`
5548 @*/
5549 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5550 {
5551   PetscFunctionBegin;
5552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5553   PetscValidType(mat, 1);
5554   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5556   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5557   PetscValidLogicalCollectiveScalar(mat, a, 2);
5558   MatCheckPreallocated(mat, 1);
5559 
5560   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5561   if (a != (PetscScalar)1.0) {
5562     PetscUseTypeMethod(mat, scale, a);
5563     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5564   }
5565   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5566   PetscFunctionReturn(PETSC_SUCCESS);
5567 }
5568 
5569 /*@
5570    MatNorm - Calculates various norms of a matrix.
5571 
5572    Collective
5573 
5574    Input Parameters:
5575 +  mat - the matrix
5576 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5577 
5578    Output Parameter:
5579 .  nrm - the resulting norm
5580 
5581    Level: intermediate
5582 
5583 .seealso: `Mat`
5584 @*/
5585 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5586 {
5587   PetscFunctionBegin;
5588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5589   PetscValidType(mat, 1);
5590   PetscValidRealPointer(nrm, 3);
5591 
5592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5593   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5594   MatCheckPreallocated(mat, 1);
5595 
5596   PetscUseTypeMethod(mat, norm, type, nrm);
5597   PetscFunctionReturn(PETSC_SUCCESS);
5598 }
5599 
5600 /*
5601      This variable is used to prevent counting of MatAssemblyBegin() that
5602    are called from within a MatAssemblyEnd().
5603 */
5604 static PetscInt MatAssemblyEnd_InUse = 0;
5605 /*@
5606    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5607    be called after completing all calls to `MatSetValues()`.
5608 
5609    Collective
5610 
5611    Input Parameters:
5612 +  mat - the matrix
5613 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5614 
5615    Notes:
5616    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5617    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5618 
5619    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5620    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5621    using the matrix.
5622 
5623    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5624    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
5625    a global collective operation requiring all processes that share the matrix.
5626 
5627    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5628    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5629    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5630 
5631    Level: beginner
5632 
5633 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5634 @*/
5635 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5636 {
5637   PetscFunctionBegin;
5638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5639   PetscValidType(mat, 1);
5640   MatCheckPreallocated(mat, 1);
5641   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5642   if (mat->assembled) {
5643     mat->was_assembled = PETSC_TRUE;
5644     mat->assembled     = PETSC_FALSE;
5645   }
5646 
5647   if (!MatAssemblyEnd_InUse) {
5648     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5649     PetscTryTypeMethod(mat, assemblybegin, type);
5650     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5651   } else PetscTryTypeMethod(mat, assemblybegin, type);
5652   PetscFunctionReturn(PETSC_SUCCESS);
5653 }
5654 
5655 /*@
5656    MatAssembled - Indicates if a matrix has been assembled and is ready for
5657      use; for example, in matrix-vector product.
5658 
5659    Not Collective
5660 
5661    Input Parameter:
5662 .  mat - the matrix
5663 
5664    Output Parameter:
5665 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5666 
5667    Level: advanced
5668 
5669 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5670 @*/
5671 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5672 {
5673   PetscFunctionBegin;
5674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5675   PetscValidBoolPointer(assembled, 2);
5676   *assembled = mat->assembled;
5677   PetscFunctionReturn(PETSC_SUCCESS);
5678 }
5679 
5680 /*@
5681    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5682    be called after `MatAssemblyBegin()`.
5683 
5684    Collective on Mat
5685 
5686    Input Parameters:
5687 +  mat - the matrix
5688 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5689 
5690    Options Database Keys:
5691 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5692 .  -mat_view ::ascii_info_detail - Prints more detailed info
5693 .  -mat_view - Prints matrix in ASCII format
5694 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5695 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5696 .  -display <name> - Sets display name (default is host)
5697 .  -draw_pause <sec> - Sets number of seconds to pause after display
5698 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5699 .  -viewer_socket_machine <machine> - Machine to use for socket
5700 .  -viewer_socket_port <port> - Port number to use for socket
5701 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5702 
5703    Level: beginner
5704 
5705 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5706 @*/
5707 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5708 {
5709   static PetscInt inassm = 0;
5710   PetscBool       flg    = PETSC_FALSE;
5711 
5712   PetscFunctionBegin;
5713   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5714   PetscValidType(mat, 1);
5715 
5716   inassm++;
5717   MatAssemblyEnd_InUse++;
5718   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5719     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5720     PetscTryTypeMethod(mat, assemblyend, type);
5721     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5722   } else PetscTryTypeMethod(mat, assemblyend, type);
5723 
5724   /* Flush assembly is not a true assembly */
5725   if (type != MAT_FLUSH_ASSEMBLY) {
5726     if (mat->num_ass) {
5727       if (!mat->symmetry_eternal) {
5728         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5729         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5730       }
5731       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5732       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5733     }
5734     mat->num_ass++;
5735     mat->assembled        = PETSC_TRUE;
5736     mat->ass_nonzerostate = mat->nonzerostate;
5737   }
5738 
5739   mat->insertmode = NOT_SET_VALUES;
5740   MatAssemblyEnd_InUse--;
5741   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5742   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5743     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5744 
5745     if (mat->checksymmetryonassembly) {
5746       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5747       if (flg) {
5748         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5749       } else {
5750         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5751       }
5752     }
5753     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5754   }
5755   inassm--;
5756   PetscFunctionReturn(PETSC_SUCCESS);
5757 }
5758 
5759 /*@
5760    MatSetOption - Sets a parameter option for a matrix. Some options
5761    may be specific to certain storage formats.  Some options
5762    determine how values will be inserted (or added). Sorted,
5763    row-oriented input will generally assemble the fastest. The default
5764    is row-oriented.
5765 
5766    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5767 
5768    Input Parameters:
5769 +  mat - the matrix
5770 .  option - the option, one of those listed below (and possibly others),
5771 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5772 
5773   Options Describing Matrix Structure:
5774 +    `MAT_SPD` - symmetric positive definite
5775 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5776 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5777 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5778 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5779 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5780 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5781 
5782    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5783    do not need to be computed (usually at a high cost)
5784 
5785    Options For Use with `MatSetValues()`:
5786    Insert a logically dense subblock, which can be
5787 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5788 
5789    Note these options reflect the data you pass in with `MatSetValues()`; it has
5790    nothing to do with how the data is stored internally in the matrix
5791    data structure.
5792 
5793    When (re)assembling a matrix, we can restrict the input for
5794    efficiency/debugging purposes.  These options include
5795 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5796 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5797 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5798 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5799 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5800 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5801         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5802         performance for very large process counts.
5803 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5804         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5805         functions, instead sending only neighbor messages.
5806 
5807    Notes:
5808    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5809 
5810    Some options are relevant only for particular matrix types and
5811    are thus ignored by others.  Other options are not supported by
5812    certain matrix types and will generate an error message if set.
5813 
5814    If using Fortran to compute a matrix, one may need to
5815    use the column-oriented option (or convert to the row-oriented
5816    format).
5817 
5818    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5819    that would generate a new entry in the nonzero structure is instead
5820    ignored.  Thus, if memory has not alredy been allocated for this particular
5821    data, then the insertion is ignored. For dense matrices, in which
5822    the entire array is allocated, no entries are ever ignored.
5823    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5824 
5825    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5826    that would generate a new entry in the nonzero structure instead produces
5827    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
5828 
5829    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5830    that would generate a new entry that has not been preallocated will
5831    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5832    only.) This is a useful flag when debugging matrix memory preallocation.
5833    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5834 
5835    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5836    other processors should be dropped, rather than stashed.
5837    This is useful if you know that the "owning" processor is also
5838    always generating the correct matrix entries, so that PETSc need
5839    not transfer duplicate entries generated on another processor.
5840 
5841    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5842    searches during matrix assembly. When this flag is set, the hash table
5843    is created during the first matrix assembly. This hash table is
5844    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5845    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5846    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5847    supported by` MATMPIBAIJ` format only.
5848 
5849    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5850    are kept in the nonzero structure
5851 
5852    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5853    a zero location in the matrix
5854 
5855    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5856 
5857    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5858         zero row routines and thus improves performance for very large process counts.
5859 
5860    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5861         part of the matrix (since they should match the upper triangular part).
5862 
5863    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5864                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5865                      with finite difference schemes with non-periodic boundary conditions.
5866 
5867    Developer Note:
5868    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5869    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5870    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5871    not changed.
5872 
5873    Level: intermediate
5874 
5875 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5876 @*/
5877 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5878 {
5879   PetscFunctionBegin;
5880   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5881   if (op > 0) {
5882     PetscValidLogicalCollectiveEnum(mat, op, 2);
5883     PetscValidLogicalCollectiveBool(mat, flg, 3);
5884   }
5885 
5886   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);
5887 
5888   switch (op) {
5889   case MAT_FORCE_DIAGONAL_ENTRIES:
5890     mat->force_diagonals = flg;
5891     PetscFunctionReturn(PETSC_SUCCESS);
5892   case MAT_NO_OFF_PROC_ENTRIES:
5893     mat->nooffprocentries = flg;
5894     PetscFunctionReturn(PETSC_SUCCESS);
5895   case MAT_SUBSET_OFF_PROC_ENTRIES:
5896     mat->assembly_subset = flg;
5897     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5898 #if !defined(PETSC_HAVE_MPIUNI)
5899       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5900 #endif
5901       mat->stash.first_assembly_done = PETSC_FALSE;
5902     }
5903     PetscFunctionReturn(PETSC_SUCCESS);
5904   case MAT_NO_OFF_PROC_ZERO_ROWS:
5905     mat->nooffproczerorows = flg;
5906     PetscFunctionReturn(PETSC_SUCCESS);
5907   case MAT_SPD:
5908     if (flg) {
5909       mat->spd                    = PETSC_BOOL3_TRUE;
5910       mat->symmetric              = PETSC_BOOL3_TRUE;
5911       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5912     } else {
5913       mat->spd = PETSC_BOOL3_FALSE;
5914     }
5915     break;
5916   case MAT_SYMMETRIC:
5917     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5918     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5919 #if !defined(PETSC_USE_COMPLEX)
5920     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5921 #endif
5922     break;
5923   case MAT_HERMITIAN:
5924     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5925     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5926 #if !defined(PETSC_USE_COMPLEX)
5927     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5928 #endif
5929     break;
5930   case MAT_STRUCTURALLY_SYMMETRIC:
5931     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5932     break;
5933   case MAT_SYMMETRY_ETERNAL:
5934     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");
5935     mat->symmetry_eternal = flg;
5936     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5937     break;
5938   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5939     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");
5940     mat->structural_symmetry_eternal = flg;
5941     break;
5942   case MAT_SPD_ETERNAL:
5943     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");
5944     mat->spd_eternal = flg;
5945     if (flg) {
5946       mat->structural_symmetry_eternal = PETSC_TRUE;
5947       mat->symmetry_eternal            = PETSC_TRUE;
5948     }
5949     break;
5950   case MAT_STRUCTURE_ONLY:
5951     mat->structure_only = flg;
5952     break;
5953   case MAT_SORTED_FULL:
5954     mat->sortedfull = flg;
5955     break;
5956   default:
5957     break;
5958   }
5959   PetscTryTypeMethod(mat, setoption, op, flg);
5960   PetscFunctionReturn(PETSC_SUCCESS);
5961 }
5962 
5963 /*@
5964    MatGetOption - Gets a parameter option that has been set for a matrix.
5965 
5966    Logically Collective
5967 
5968    Input Parameters:
5969 +  mat - the matrix
5970 -  option - the option, this only responds to certain options, check the code for which ones
5971 
5972    Output Parameter:
5973 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5974 
5975     Notes:
5976     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5977 
5978     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5979     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5980 
5981    Level: intermediate
5982 
5983 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5984     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5985 @*/
5986 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5987 {
5988   PetscFunctionBegin;
5989   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5990   PetscValidType(mat, 1);
5991 
5992   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);
5993   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()");
5994 
5995   switch (op) {
5996   case MAT_NO_OFF_PROC_ENTRIES:
5997     *flg = mat->nooffprocentries;
5998     break;
5999   case MAT_NO_OFF_PROC_ZERO_ROWS:
6000     *flg = mat->nooffproczerorows;
6001     break;
6002   case MAT_SYMMETRIC:
6003     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6004     break;
6005   case MAT_HERMITIAN:
6006     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6007     break;
6008   case MAT_STRUCTURALLY_SYMMETRIC:
6009     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6010     break;
6011   case MAT_SPD:
6012     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6013     break;
6014   case MAT_SYMMETRY_ETERNAL:
6015     *flg = mat->symmetry_eternal;
6016     break;
6017   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6018     *flg = mat->symmetry_eternal;
6019     break;
6020   default:
6021     break;
6022   }
6023   PetscFunctionReturn(PETSC_SUCCESS);
6024 }
6025 
6026 /*@
6027    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6028    this routine retains the old nonzero structure.
6029 
6030    Logically Collective
6031 
6032    Input Parameters:
6033 .  mat - the matrix
6034 
6035    Level: intermediate
6036 
6037    Note:
6038     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.
6039    See the Performance chapter of the users manual for information on preallocating matrices.
6040 
6041 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6042 @*/
6043 PetscErrorCode MatZeroEntries(Mat mat)
6044 {
6045   PetscFunctionBegin;
6046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6047   PetscValidType(mat, 1);
6048   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6049   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");
6050   MatCheckPreallocated(mat, 1);
6051 
6052   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6053   PetscUseTypeMethod(mat, zeroentries);
6054   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6055   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6056   PetscFunctionReturn(PETSC_SUCCESS);
6057 }
6058 
6059 /*@
6060    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6061    of a set of rows and columns of a matrix.
6062 
6063    Collective
6064 
6065    Input Parameters:
6066 +  mat - the matrix
6067 .  numRows - the number of rows to remove
6068 .  rows - the global row indices
6069 .  diag - value put in the diagonal of the eliminated rows
6070 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6071 -  b - optional vector of right hand side, that will be adjusted by provided solution
6072 
6073    Notes:
6074    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6075 
6076    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6077    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
6078 
6079    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6080    Krylov method to take advantage of the known solution on the zeroed rows.
6081 
6082    For the parallel case, all processes that share the matrix (i.e.,
6083    those in the communicator used for matrix creation) MUST call this
6084    routine, regardless of whether any rows being zeroed are owned by
6085    them.
6086 
6087    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6088 
6089    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6090    list only rows local to itself).
6091 
6092    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6093 
6094    Level: intermediate
6095 
6096 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6097           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6098 @*/
6099 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6100 {
6101   PetscFunctionBegin;
6102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6103   PetscValidType(mat, 1);
6104   if (numRows) PetscValidIntPointer(rows, 3);
6105   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6106   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6107   MatCheckPreallocated(mat, 1);
6108 
6109   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6110   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6111   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6112   PetscFunctionReturn(PETSC_SUCCESS);
6113 }
6114 
6115 /*@
6116    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6117    of a set of rows and columns of a matrix.
6118 
6119    Collective
6120 
6121    Input Parameters:
6122 +  mat - the matrix
6123 .  is - the rows to zero
6124 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6125 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6126 -  b - optional vector of right hand side, that will be adjusted by provided solution
6127 
6128    Note:
6129    See `MatZeroRowsColumns()` for details on how this routine operates.
6130 
6131    Level: intermediate
6132 
6133 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6134           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6135 @*/
6136 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6137 {
6138   PetscInt        numRows;
6139   const PetscInt *rows;
6140 
6141   PetscFunctionBegin;
6142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6143   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6144   PetscValidType(mat, 1);
6145   PetscValidType(is, 2);
6146   PetscCall(ISGetLocalSize(is, &numRows));
6147   PetscCall(ISGetIndices(is, &rows));
6148   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6149   PetscCall(ISRestoreIndices(is, &rows));
6150   PetscFunctionReturn(PETSC_SUCCESS);
6151 }
6152 
6153 /*@
6154    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6155    of a set of rows of a matrix.
6156 
6157    Collective
6158 
6159    Input Parameters:
6160 +  mat - the matrix
6161 .  numRows - the number of rows to remove
6162 .  rows - the global row indices
6163 .  diag - value put in the diagonal of the eliminated rows
6164 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6165 -  b - optional vector of right hand side, that will be adjusted by provided solution
6166 
6167    Notes:
6168    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6169 
6170    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6171 
6172    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6173    Krylov method to take advantage of the known solution on the zeroed rows.
6174 
6175    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
6176    from the matrix.
6177 
6178    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6179    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
6180    formats this does not alter the nonzero structure.
6181 
6182    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6183    of the matrix is not changed the values are
6184    merely zeroed.
6185 
6186    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6187    formats can optionally remove the main diagonal entry from the
6188    nonzero structure as well, by passing 0.0 as the final argument).
6189 
6190    For the parallel case, all processes that share the matrix (i.e.,
6191    those in the communicator used for matrix creation) MUST call this
6192    routine, regardless of whether any rows being zeroed are owned by
6193    them.
6194 
6195    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6196    list only rows local to itself).
6197 
6198    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6199    owns that are to be zeroed. This saves a global synchronization in the implementation.
6200 
6201    Level: intermediate
6202 
6203 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6204           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6205 @*/
6206 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6207 {
6208   PetscFunctionBegin;
6209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6210   PetscValidType(mat, 1);
6211   if (numRows) PetscValidIntPointer(rows, 3);
6212   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6213   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6214   MatCheckPreallocated(mat, 1);
6215 
6216   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6217   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6218   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6219   PetscFunctionReturn(PETSC_SUCCESS);
6220 }
6221 
6222 /*@
6223    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6224    of a set of rows of a matrix.
6225 
6226    Collective on Mat
6227 
6228    Input Parameters:
6229 +  mat - the matrix
6230 .  is - index set of rows to remove (if NULL then no row is removed)
6231 .  diag - value put in all diagonals of eliminated rows
6232 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6233 -  b - optional vector of right hand side, that will be adjusted by provided solution
6234 
6235    Note:
6236    See `MatZeroRows()` for details on how this routine operates.
6237 
6238    Level: intermediate
6239 
6240 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6241           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6242 @*/
6243 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6244 {
6245   PetscInt        numRows = 0;
6246   const PetscInt *rows    = NULL;
6247 
6248   PetscFunctionBegin;
6249   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6250   PetscValidType(mat, 1);
6251   if (is) {
6252     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6253     PetscCall(ISGetLocalSize(is, &numRows));
6254     PetscCall(ISGetIndices(is, &rows));
6255   }
6256   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6257   if (is) PetscCall(ISRestoreIndices(is, &rows));
6258   PetscFunctionReturn(PETSC_SUCCESS);
6259 }
6260 
6261 /*@
6262    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6263    of a set of rows of a matrix. These rows must be local to the process.
6264 
6265    Collective
6266 
6267    Input Parameters:
6268 +  mat - the matrix
6269 .  numRows - the number of rows to remove
6270 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6271 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6272 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6273 -  b - optional vector of right hand side, that will be adjusted by provided solution
6274 
6275    Level: intermediate
6276 
6277    Notes:
6278    See `MatZeroRows()` for details on how this routine operates.
6279 
6280    The grid coordinates are across the entire grid, not just the local portion
6281 
6282    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6283    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6284    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6285    `DM_BOUNDARY_PERIODIC` boundary type.
6286 
6287    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
6288    a single value per point) you can skip filling those indices.
6289 
6290    Fortran Note:
6291    idxm and idxn should be declared as
6292 $     MatStencil idxm(4,m)
6293    and the values inserted using
6294 .vb
6295     idxm(MatStencil_i,1) = i
6296     idxm(MatStencil_j,1) = j
6297     idxm(MatStencil_k,1) = k
6298     idxm(MatStencil_c,1) = c
6299    etc
6300 .ve
6301 
6302 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6303           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6304 @*/
6305 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6306 {
6307   PetscInt  dim    = mat->stencil.dim;
6308   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6309   PetscInt *dims   = mat->stencil.dims + 1;
6310   PetscInt *starts = mat->stencil.starts;
6311   PetscInt *dxm    = (PetscInt *)rows;
6312   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6313 
6314   PetscFunctionBegin;
6315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6316   PetscValidType(mat, 1);
6317   if (numRows) PetscValidPointer(rows, 3);
6318 
6319   PetscCall(PetscMalloc1(numRows, &jdxm));
6320   for (i = 0; i < numRows; ++i) {
6321     /* Skip unused dimensions (they are ordered k, j, i, c) */
6322     for (j = 0; j < 3 - sdim; ++j) dxm++;
6323     /* Local index in X dir */
6324     tmp = *dxm++ - starts[0];
6325     /* Loop over remaining dimensions */
6326     for (j = 0; j < dim - 1; ++j) {
6327       /* If nonlocal, set index to be negative */
6328       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6329       /* Update local index */
6330       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6331     }
6332     /* Skip component slot if necessary */
6333     if (mat->stencil.noc) dxm++;
6334     /* Local row number */
6335     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6336   }
6337   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6338   PetscCall(PetscFree(jdxm));
6339   PetscFunctionReturn(PETSC_SUCCESS);
6340 }
6341 
6342 /*@
6343    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6344    of a set of rows and columns of a matrix.
6345 
6346    Collective
6347 
6348    Input Parameters:
6349 +  mat - the matrix
6350 .  numRows - the number of rows/columns to remove
6351 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6352 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6353 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6354 -  b - optional vector of right hand side, that will be adjusted by provided solution
6355 
6356    Level: intermediate
6357 
6358    Notes:
6359    See `MatZeroRowsColumns()` for details on how this routine operates.
6360 
6361    The grid coordinates are across the entire grid, not just the local portion
6362 
6363    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6364    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6365    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6366    `DM_BOUNDARY_PERIODIC` boundary type.
6367 
6368    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
6369    a single value per point) you can skip filling those indices.
6370 
6371    Fortran Note:
6372    In Fortran idxm and idxn should be declared as
6373 $     MatStencil idxm(4,m)
6374    and the values inserted using
6375 .vb
6376     idxm(MatStencil_i,1) = i
6377     idxm(MatStencil_j,1) = j
6378     idxm(MatStencil_k,1) = k
6379     idxm(MatStencil_c,1) = c
6380     etc
6381 .ve
6382 
6383 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6384           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6385 @*/
6386 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6387 {
6388   PetscInt  dim    = mat->stencil.dim;
6389   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6390   PetscInt *dims   = mat->stencil.dims + 1;
6391   PetscInt *starts = mat->stencil.starts;
6392   PetscInt *dxm    = (PetscInt *)rows;
6393   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6394 
6395   PetscFunctionBegin;
6396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6397   PetscValidType(mat, 1);
6398   if (numRows) PetscValidPointer(rows, 3);
6399 
6400   PetscCall(PetscMalloc1(numRows, &jdxm));
6401   for (i = 0; i < numRows; ++i) {
6402     /* Skip unused dimensions (they are ordered k, j, i, c) */
6403     for (j = 0; j < 3 - sdim; ++j) dxm++;
6404     /* Local index in X dir */
6405     tmp = *dxm++ - starts[0];
6406     /* Loop over remaining dimensions */
6407     for (j = 0; j < dim - 1; ++j) {
6408       /* If nonlocal, set index to be negative */
6409       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6410       /* Update local index */
6411       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6412     }
6413     /* Skip component slot if necessary */
6414     if (mat->stencil.noc) dxm++;
6415     /* Local row number */
6416     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6417   }
6418   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6419   PetscCall(PetscFree(jdxm));
6420   PetscFunctionReturn(PETSC_SUCCESS);
6421 }
6422 
6423 /*@C
6424    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6425    of a set of rows of a matrix; using local numbering of rows.
6426 
6427    Collective
6428 
6429    Input Parameters:
6430 +  mat - the matrix
6431 .  numRows - the number of rows to remove
6432 .  rows - the local row indices
6433 .  diag - value put in all diagonals of eliminated rows
6434 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6435 -  b - optional vector of right hand side, that will be adjusted by provided solution
6436 
6437    Notes:
6438    Before calling `MatZeroRowsLocal()`, the user must first set the
6439    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6440 
6441    See `MatZeroRows()` for details on how this routine operates.
6442 
6443    Level: intermediate
6444 
6445 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6446           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6447 @*/
6448 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6449 {
6450   PetscFunctionBegin;
6451   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6452   PetscValidType(mat, 1);
6453   if (numRows) PetscValidIntPointer(rows, 3);
6454   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6455   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6456   MatCheckPreallocated(mat, 1);
6457 
6458   if (mat->ops->zerorowslocal) {
6459     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6460   } else {
6461     IS              is, newis;
6462     const PetscInt *newRows;
6463 
6464     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6465     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6466     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6467     PetscCall(ISGetIndices(newis, &newRows));
6468     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6469     PetscCall(ISRestoreIndices(newis, &newRows));
6470     PetscCall(ISDestroy(&newis));
6471     PetscCall(ISDestroy(&is));
6472   }
6473   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6474   PetscFunctionReturn(PETSC_SUCCESS);
6475 }
6476 
6477 /*@
6478    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6479    of a set of rows of a matrix; using local numbering of rows.
6480 
6481    Collective
6482 
6483    Input Parameters:
6484 +  mat - the matrix
6485 .  is - index set of rows to remove
6486 .  diag - value put in all diagonals of eliminated rows
6487 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6488 -  b - optional vector of right hand side, that will be adjusted by provided solution
6489 
6490    Notes:
6491    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6492    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6493 
6494    See `MatZeroRows()` for details on how this routine operates.
6495 
6496    Level: intermediate
6497 
6498 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6499           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6500 @*/
6501 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6502 {
6503   PetscInt        numRows;
6504   const PetscInt *rows;
6505 
6506   PetscFunctionBegin;
6507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6508   PetscValidType(mat, 1);
6509   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6510   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6511   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6512   MatCheckPreallocated(mat, 1);
6513 
6514   PetscCall(ISGetLocalSize(is, &numRows));
6515   PetscCall(ISGetIndices(is, &rows));
6516   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6517   PetscCall(ISRestoreIndices(is, &rows));
6518   PetscFunctionReturn(PETSC_SUCCESS);
6519 }
6520 
6521 /*@
6522    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6523    of a set of rows and columns of a matrix; using local numbering of rows.
6524 
6525    Collective
6526 
6527    Input Parameters:
6528 +  mat - the matrix
6529 .  numRows - the number of rows to remove
6530 .  rows - the global row indices
6531 .  diag - value put in all diagonals of eliminated rows
6532 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6533 -  b - optional vector of right hand side, that will be adjusted by provided solution
6534 
6535    Notes:
6536    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6537    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6538 
6539    See `MatZeroRowsColumns()` for details on how this routine operates.
6540 
6541    Level: intermediate
6542 
6543 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6544           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6545 @*/
6546 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6547 {
6548   IS              is, newis;
6549   const PetscInt *newRows;
6550 
6551   PetscFunctionBegin;
6552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6553   PetscValidType(mat, 1);
6554   if (numRows) PetscValidIntPointer(rows, 3);
6555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6556   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6557   MatCheckPreallocated(mat, 1);
6558 
6559   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6560   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6561   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6562   PetscCall(ISGetIndices(newis, &newRows));
6563   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6564   PetscCall(ISRestoreIndices(newis, &newRows));
6565   PetscCall(ISDestroy(&newis));
6566   PetscCall(ISDestroy(&is));
6567   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6568   PetscFunctionReturn(PETSC_SUCCESS);
6569 }
6570 
6571 /*@
6572    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6573    of a set of rows and columns of a matrix; using local numbering of rows.
6574 
6575    Collective on Mat
6576 
6577    Input Parameters:
6578 +  mat - the matrix
6579 .  is - index set of rows to remove
6580 .  diag - value put in all diagonals of eliminated rows
6581 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6582 -  b - optional vector of right hand side, that will be adjusted by provided solution
6583 
6584    Notes:
6585    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6586    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6587 
6588    See `MatZeroRowsColumns()` for details on how this routine operates.
6589 
6590    Level: intermediate
6591 
6592 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6593           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6594 @*/
6595 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6596 {
6597   PetscInt        numRows;
6598   const PetscInt *rows;
6599 
6600   PetscFunctionBegin;
6601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6602   PetscValidType(mat, 1);
6603   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6604   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6605   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6606   MatCheckPreallocated(mat, 1);
6607 
6608   PetscCall(ISGetLocalSize(is, &numRows));
6609   PetscCall(ISGetIndices(is, &rows));
6610   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6611   PetscCall(ISRestoreIndices(is, &rows));
6612   PetscFunctionReturn(PETSC_SUCCESS);
6613 }
6614 
6615 /*@C
6616    MatGetSize - Returns the numbers of rows and columns in a matrix.
6617 
6618    Not Collective
6619 
6620    Input Parameter:
6621 .  mat - the matrix
6622 
6623    Output Parameters:
6624 +  m - the number of global rows
6625 -  n - the number of global columns
6626 
6627    Note: both output parameters can be NULL on input.
6628 
6629    Level: beginner
6630 
6631 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6632 @*/
6633 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6634 {
6635   PetscFunctionBegin;
6636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6637   if (m) *m = mat->rmap->N;
6638   if (n) *n = mat->cmap->N;
6639   PetscFunctionReturn(PETSC_SUCCESS);
6640 }
6641 
6642 /*@C
6643    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6644    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6645 
6646    Not Collective
6647 
6648    Input Parameter:
6649 .  mat - the matrix
6650 
6651    Output Parameters:
6652 +  m - the number of local rows, use `NULL` to not obtain this value
6653 -  n - the number of local columns, use `NULL` to not obtain this value
6654 
6655    Level: beginner
6656 
6657 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6658 @*/
6659 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6660 {
6661   PetscFunctionBegin;
6662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6663   if (m) PetscValidIntPointer(m, 2);
6664   if (n) PetscValidIntPointer(n, 3);
6665   if (m) *m = mat->rmap->n;
6666   if (n) *n = mat->cmap->n;
6667   PetscFunctionReturn(PETSC_SUCCESS);
6668 }
6669 
6670 /*@C
6671    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6672    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6673 
6674    Not Collective, unless matrix has not been allocated, then collective
6675 
6676    Input Parameter:
6677 .  mat - the matrix
6678 
6679    Output Parameters:
6680 +  m - the global index of the first local column, use `NULL` to not obtain this value
6681 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6682 
6683    Level: developer
6684 
6685 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6686 @*/
6687 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6688 {
6689   PetscFunctionBegin;
6690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6691   PetscValidType(mat, 1);
6692   if (m) PetscValidIntPointer(m, 2);
6693   if (n) PetscValidIntPointer(n, 3);
6694   MatCheckPreallocated(mat, 1);
6695   if (m) *m = mat->cmap->rstart;
6696   if (n) *n = mat->cmap->rend;
6697   PetscFunctionReturn(PETSC_SUCCESS);
6698 }
6699 
6700 /*@C
6701    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6702    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6703    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6704 
6705    Not Collective
6706 
6707    Input Parameter:
6708 .  mat - the matrix
6709 
6710    Output Parameters:
6711 +  m - the global index of the first local row, use `NULL` to not obtain this value
6712 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6713 
6714    Note:
6715   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6716   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6717   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6718 
6719    Level: beginner
6720 
6721 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6722           `PetscLayout`
6723 @*/
6724 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6725 {
6726   PetscFunctionBegin;
6727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6728   PetscValidType(mat, 1);
6729   if (m) PetscValidIntPointer(m, 2);
6730   if (n) PetscValidIntPointer(n, 3);
6731   MatCheckPreallocated(mat, 1);
6732   if (m) *m = mat->rmap->rstart;
6733   if (n) *n = mat->rmap->rend;
6734   PetscFunctionReturn(PETSC_SUCCESS);
6735 }
6736 
6737 /*@C
6738    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6739    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
6740    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6741 
6742    Not Collective, unless matrix has not been allocated, then collective
6743 
6744    Input Parameters:
6745 .  mat - the matrix
6746 
6747    Output Parameters:
6748 .  ranges - start of each processors portion plus one more than the total length at the end
6749 
6750    Level: beginner
6751 
6752 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6753 @*/
6754 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6755 {
6756   PetscFunctionBegin;
6757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6758   PetscValidType(mat, 1);
6759   MatCheckPreallocated(mat, 1);
6760   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6761   PetscFunctionReturn(PETSC_SUCCESS);
6762 }
6763 
6764 /*@C
6765    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6766    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6767 
6768    Not Collective, unless matrix has not been allocated, then collective on Mat
6769 
6770    Input Parameters:
6771 .  mat - the matrix
6772 
6773    Output Parameters:
6774 .  ranges - start of each processors portion plus one more then the total length at the end
6775 
6776    Level: beginner
6777 
6778 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6779 @*/
6780 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6781 {
6782   PetscFunctionBegin;
6783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6784   PetscValidType(mat, 1);
6785   MatCheckPreallocated(mat, 1);
6786   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6787   PetscFunctionReturn(PETSC_SUCCESS);
6788 }
6789 
6790 /*@C
6791    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6792    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6793    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6794 
6795    Not Collective
6796 
6797    Input Parameter:
6798 .  A - matrix
6799 
6800    Output Parameters:
6801 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6802 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6803 
6804    Level: intermediate
6805 
6806 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6807 @*/
6808 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6809 {
6810   PetscErrorCode (*f)(Mat, IS *, IS *);
6811 
6812   PetscFunctionBegin;
6813   MatCheckPreallocated(A, 1);
6814   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6815   if (f) {
6816     PetscCall((*f)(A, rows, cols));
6817   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6818     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6819     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6820   }
6821   PetscFunctionReturn(PETSC_SUCCESS);
6822 }
6823 
6824 /*@C
6825    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6826    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6827    to complete the factorization.
6828 
6829    Collective on fact
6830 
6831    Input Parameters:
6832 +  fact - the factorized matrix obtained with `MatGetFactor()`
6833 .  mat - the matrix
6834 .  row - row permutation
6835 .  column - column permutation
6836 -  info - structure containing
6837 $      levels - number of levels of fill.
6838 $      expected fill - as ratio of original fill.
6839 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6840                 missing diagonal entries)
6841 
6842    Output Parameters:
6843 .  fact - new matrix that has been symbolically factored
6844 
6845    Level: developer
6846 
6847    Notes:
6848    See [Matrix Factorization](sec_matfactor) for additional information.
6849 
6850    Most users should employ the `KSP` interface for linear solvers
6851    instead of working directly with matrix algebra routines such as this.
6852    See, e.g., `KSPCreate()`.
6853 
6854    Uses the definition of level of fill as in Y. Saad, 2003
6855 
6856    Developer Note:
6857    The Fortran interface is not autogenerated as the
6858    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6859 
6860    References:
6861 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6862 
6863 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6864           `MatGetOrdering()`, `MatFactorInfo`
6865 @*/
6866 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6867 {
6868   PetscFunctionBegin;
6869   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6870   PetscValidType(mat, 2);
6871   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6872   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6873   PetscValidPointer(info, 5);
6874   PetscValidPointer(fact, 1);
6875   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6876   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6877   if (!fact->ops->ilufactorsymbolic) {
6878     MatSolverType stype;
6879     PetscCall(MatFactorGetSolverType(fact, &stype));
6880     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6881   }
6882   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6883   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6884   MatCheckPreallocated(mat, 2);
6885 
6886   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6887   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6888   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6889   PetscFunctionReturn(PETSC_SUCCESS);
6890 }
6891 
6892 /*@C
6893    MatICCFactorSymbolic - Performs symbolic incomplete
6894    Cholesky factorization for a symmetric matrix.  Use
6895    `MatCholeskyFactorNumeric()` to complete the factorization.
6896 
6897    Collective on fact
6898 
6899    Input Parameters:
6900 +  fact - the factorized matrix obtained with `MatGetFactor()`
6901 .  mat - the matrix to be factored
6902 .  perm - row and column permutation
6903 -  info - structure containing
6904 $      levels - number of levels of fill.
6905 $      expected fill - as ratio of original fill.
6906 
6907    Output Parameter:
6908 .  fact - the factored matrix
6909 
6910    Level: developer
6911 
6912    Notes:
6913    Most users should employ the `KSP` interface for linear solvers
6914    instead of working directly with matrix algebra routines such as this.
6915    See, e.g., `KSPCreate()`.
6916 
6917    This uses the definition of level of fill as in Y. Saad, 2003
6918 
6919    Developer Note:
6920    The Fortran interface is not autogenerated as the
6921    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6922 
6923    References:
6924 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6925 
6926 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6927 @*/
6928 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6929 {
6930   PetscFunctionBegin;
6931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6932   PetscValidType(mat, 2);
6933   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6934   PetscValidPointer(info, 4);
6935   PetscValidPointer(fact, 1);
6936   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6937   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6938   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6939   if (!(fact)->ops->iccfactorsymbolic) {
6940     MatSolverType stype;
6941     PetscCall(MatFactorGetSolverType(fact, &stype));
6942     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6943   }
6944   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6945   MatCheckPreallocated(mat, 2);
6946 
6947   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6948   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6949   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6950   PetscFunctionReturn(PETSC_SUCCESS);
6951 }
6952 
6953 /*@C
6954    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6955    points to an array of valid matrices, they may be reused to store the new
6956    submatrices.
6957 
6958    Collective
6959 
6960    Input Parameters:
6961 +  mat - the matrix
6962 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6963 .  irow, icol - index sets of rows and columns to extract
6964 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6965 
6966    Output Parameter:
6967 .  submat - the array of submatrices
6968 
6969    Notes:
6970    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6971    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6972    to extract a parallel submatrix.
6973 
6974    Some matrix types place restrictions on the row and column
6975    indices, such as that they be sorted or that they be equal to each other.
6976 
6977    The index sets may not have duplicate entries.
6978 
6979    When extracting submatrices from a parallel matrix, each processor can
6980    form a different submatrix by setting the rows and columns of its
6981    individual index sets according to the local submatrix desired.
6982 
6983    When finished using the submatrices, the user should destroy
6984    them with `MatDestroySubMatrices()`.
6985 
6986    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6987    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6988 
6989    This routine creates the matrices in submat; you should NOT create them before
6990    calling it. It also allocates the array of matrix pointers submat.
6991 
6992    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6993    request one row/column in a block, they must request all rows/columns that are in
6994    that block. For example, if the block size is 2 you cannot request just row 0 and
6995    column 0.
6996 
6997    Fortran Note:
6998    The Fortran interface is slightly different from that given below; it
6999    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
7000 
7001    Level: advanced
7002 
7003 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7004 @*/
7005 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7006 {
7007   PetscInt  i;
7008   PetscBool eq;
7009 
7010   PetscFunctionBegin;
7011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7012   PetscValidType(mat, 1);
7013   if (n) {
7014     PetscValidPointer(irow, 3);
7015     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7016     PetscValidPointer(icol, 4);
7017     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7018   }
7019   PetscValidPointer(submat, 6);
7020   if (n && scall == MAT_REUSE_MATRIX) {
7021     PetscValidPointer(*submat, 6);
7022     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7023   }
7024   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7025   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7026   MatCheckPreallocated(mat, 1);
7027   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7028   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7029   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7030   for (i = 0; i < n; i++) {
7031     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7032     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7033     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7034 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7035     if (mat->boundtocpu && mat->bindingpropagates) {
7036       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7037       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7038     }
7039 #endif
7040   }
7041   PetscFunctionReturn(PETSC_SUCCESS);
7042 }
7043 
7044 /*@C
7045    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7046 
7047    Collective
7048 
7049    Input Parameters:
7050 +  mat - the matrix
7051 .  n   - the number of submatrixes to be extracted
7052 .  irow, icol - index sets of rows and columns to extract
7053 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7054 
7055    Output Parameter:
7056 .  submat - the array of submatrices
7057 
7058    Level: advanced
7059 
7060    Note:
7061    This is used by `PCGASM`
7062 
7063 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7064 @*/
7065 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7066 {
7067   PetscInt  i;
7068   PetscBool eq;
7069 
7070   PetscFunctionBegin;
7071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7072   PetscValidType(mat, 1);
7073   if (n) {
7074     PetscValidPointer(irow, 3);
7075     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7076     PetscValidPointer(icol, 4);
7077     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7078   }
7079   PetscValidPointer(submat, 6);
7080   if (n && scall == MAT_REUSE_MATRIX) {
7081     PetscValidPointer(*submat, 6);
7082     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7083   }
7084   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7085   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7086   MatCheckPreallocated(mat, 1);
7087 
7088   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7089   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7090   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7091   for (i = 0; i < n; i++) {
7092     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7093     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7094   }
7095   PetscFunctionReturn(PETSC_SUCCESS);
7096 }
7097 
7098 /*@C
7099    MatDestroyMatrices - Destroys an array of matrices.
7100 
7101    Collective
7102 
7103    Input Parameters:
7104 +  n - the number of local matrices
7105 -  mat - the matrices (note that this is a pointer to the array of matrices)
7106 
7107    Level: advanced
7108 
7109     Note:
7110     Frees not only the matrices, but also the array that contains the matrices
7111            In Fortran will not free the array.
7112 
7113 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7114 @*/
7115 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7116 {
7117   PetscInt i;
7118 
7119   PetscFunctionBegin;
7120   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7121   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7122   PetscValidPointer(mat, 2);
7123 
7124   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7125 
7126   /* memory is allocated even if n = 0 */
7127   PetscCall(PetscFree(*mat));
7128   PetscFunctionReturn(PETSC_SUCCESS);
7129 }
7130 
7131 /*@C
7132    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7133 
7134    Collective
7135 
7136    Input Parameters:
7137 +  n - the number of local matrices
7138 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
7139                        sequence of MatCreateSubMatrices())
7140 
7141    Level: advanced
7142 
7143     Note:
7144     Frees not only the matrices, but also the array that contains the matrices
7145            In Fortran will not free the array.
7146 
7147 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7148 @*/
7149 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7150 {
7151   Mat mat0;
7152 
7153   PetscFunctionBegin;
7154   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7155   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7156   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7157   PetscValidPointer(mat, 2);
7158 
7159   mat0 = (*mat)[0];
7160   if (mat0 && mat0->ops->destroysubmatrices) {
7161     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7162   } else {
7163     PetscCall(MatDestroyMatrices(n, mat));
7164   }
7165   PetscFunctionReturn(PETSC_SUCCESS);
7166 }
7167 
7168 /*@C
7169    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7170 
7171    Collective
7172 
7173    Input Parameters:
7174 .  mat - the matrix
7175 
7176    Output Parameter:
7177 .  matstruct - the sequential matrix with the nonzero structure of mat
7178 
7179   Level: developer
7180 
7181 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7182 @*/
7183 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7184 {
7185   PetscFunctionBegin;
7186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7187   PetscValidPointer(matstruct, 2);
7188 
7189   PetscValidType(mat, 1);
7190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7191   MatCheckPreallocated(mat, 1);
7192 
7193   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7194   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7195   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7196   PetscFunctionReturn(PETSC_SUCCESS);
7197 }
7198 
7199 /*@C
7200    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7201 
7202    Collective
7203 
7204    Input Parameters:
7205 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7206                        sequence of `MatGetSequentialNonzeroStructure()`)
7207 
7208    Level: advanced
7209 
7210     Note:
7211     Frees not only the matrices, but also the array that contains the matrices
7212 
7213 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7214 @*/
7215 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7216 {
7217   PetscFunctionBegin;
7218   PetscValidPointer(mat, 1);
7219   PetscCall(MatDestroy(mat));
7220   PetscFunctionReturn(PETSC_SUCCESS);
7221 }
7222 
7223 /*@
7224    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7225    replaces the index sets by larger ones that represent submatrices with
7226    additional overlap.
7227 
7228    Collective
7229 
7230    Input Parameters:
7231 +  mat - the matrix
7232 .  n   - the number of index sets
7233 .  is  - the array of index sets (these index sets will changed during the call)
7234 -  ov  - the additional overlap requested
7235 
7236    Options Database Key:
7237 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7238 
7239    Level: developer
7240 
7241    Note:
7242    The computed overlap preserves the matrix block sizes when the blocks are square.
7243    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7244    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7245 
7246 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7247 @*/
7248 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7249 {
7250   PetscInt i, bs, cbs;
7251 
7252   PetscFunctionBegin;
7253   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7254   PetscValidType(mat, 1);
7255   PetscValidLogicalCollectiveInt(mat, n, 2);
7256   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7257   if (n) {
7258     PetscValidPointer(is, 3);
7259     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7260   }
7261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7263   MatCheckPreallocated(mat, 1);
7264 
7265   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7266   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7267   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7268   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7269   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7270   if (bs == cbs) {
7271     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7272   }
7273   PetscFunctionReturn(PETSC_SUCCESS);
7274 }
7275 
7276 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7277 
7278 /*@
7279    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7280    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7281    additional overlap.
7282 
7283    Collective
7284 
7285    Input Parameters:
7286 +  mat - the matrix
7287 .  n   - the number of index sets
7288 .  is  - the array of index sets (these index sets will changed during the call)
7289 -  ov  - the additional overlap requested
7290 
7291 `   Options Database Key:
7292 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7293 
7294    Level: developer
7295 
7296 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7297 @*/
7298 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7299 {
7300   PetscInt i;
7301 
7302   PetscFunctionBegin;
7303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7304   PetscValidType(mat, 1);
7305   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7306   if (n) {
7307     PetscValidPointer(is, 3);
7308     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7309   }
7310   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7311   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7312   MatCheckPreallocated(mat, 1);
7313   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7314   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7315   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7316   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7317   PetscFunctionReturn(PETSC_SUCCESS);
7318 }
7319 
7320 /*@
7321    MatGetBlockSize - Returns the matrix block size.
7322 
7323    Not Collective
7324 
7325    Input Parameter:
7326 .  mat - the matrix
7327 
7328    Output Parameter:
7329 .  bs - block size
7330 
7331    Notes:
7332     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7333 
7334    If the block size has not been set yet this routine returns 1.
7335 
7336    Level: intermediate
7337 
7338 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7339 @*/
7340 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7341 {
7342   PetscFunctionBegin;
7343   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7344   PetscValidIntPointer(bs, 2);
7345   *bs = PetscAbs(mat->rmap->bs);
7346   PetscFunctionReturn(PETSC_SUCCESS);
7347 }
7348 
7349 /*@
7350    MatGetBlockSizes - Returns the matrix block row and column sizes.
7351 
7352    Not Collective
7353 
7354    Input Parameter:
7355 .  mat - the matrix
7356 
7357    Output Parameters:
7358 +  rbs - row block size
7359 -  cbs - column block size
7360 
7361    Notes:
7362     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7363     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7364 
7365    If a block size has not been set yet this routine returns 1.
7366 
7367    Level: intermediate
7368 
7369 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7370 @*/
7371 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7372 {
7373   PetscFunctionBegin;
7374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7375   if (rbs) PetscValidIntPointer(rbs, 2);
7376   if (cbs) PetscValidIntPointer(cbs, 3);
7377   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7378   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7379   PetscFunctionReturn(PETSC_SUCCESS);
7380 }
7381 
7382 /*@
7383    MatSetBlockSize - Sets the matrix block size.
7384 
7385    Logically Collective
7386 
7387    Input Parameters:
7388 +  mat - the matrix
7389 -  bs - block size
7390 
7391    Notes:
7392     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7393     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7394 
7395     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7396     is compatible with the matrix local sizes.
7397 
7398    Level: intermediate
7399 
7400 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7401 @*/
7402 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7403 {
7404   PetscFunctionBegin;
7405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7406   PetscValidLogicalCollectiveInt(mat, bs, 2);
7407   PetscCall(MatSetBlockSizes(mat, bs, bs));
7408   PetscFunctionReturn(PETSC_SUCCESS);
7409 }
7410 
7411 typedef struct {
7412   PetscInt         n;
7413   IS              *is;
7414   Mat             *mat;
7415   PetscObjectState nonzerostate;
7416   Mat              C;
7417 } EnvelopeData;
7418 
7419 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7420 {
7421   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7422   PetscCall(PetscFree(edata->is));
7423   PetscCall(PetscFree(edata));
7424   return PETSC_SUCCESS;
7425 }
7426 
7427 /*
7428    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7429          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7430 
7431    Collective
7432 
7433    Input Parameter:
7434 .  mat - the matrix
7435 
7436    Notes:
7437      There can be zeros within the blocks
7438 
7439      The blocks can overlap between processes, including laying on more than two processes
7440 
7441 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7442 */
7443 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7444 {
7445   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7446   PetscInt          *diag, *odiag, sc;
7447   VecScatter         scatter;
7448   PetscScalar       *seqv;
7449   const PetscScalar *parv;
7450   const PetscInt    *ia, *ja;
7451   PetscBool          set, flag, done;
7452   Mat                AA = mat, A;
7453   MPI_Comm           comm;
7454   PetscMPIInt        rank, size, tag;
7455   MPI_Status         status;
7456   PetscContainer     container;
7457   EnvelopeData      *edata;
7458   Vec                seq, par;
7459   IS                 isglobal;
7460 
7461   PetscFunctionBegin;
7462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7463   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7464   if (!set || !flag) {
7465     /* TOO: only needs nonzero structure of transpose */
7466     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7467     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7468   }
7469   PetscCall(MatAIJGetLocalMat(AA, &A));
7470   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7471   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7472 
7473   PetscCall(MatGetLocalSize(mat, &n, NULL));
7474   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7475   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7476   PetscCallMPI(MPI_Comm_size(comm, &size));
7477   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7478 
7479   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7480 
7481   if (rank > 0) {
7482     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7483     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7484   }
7485   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7486   for (i = 0; i < n; i++) {
7487     env = PetscMax(env, ja[ia[i + 1] - 1]);
7488     II  = rstart + i;
7489     if (env == II) {
7490       starts[lblocks]  = tbs;
7491       sizes[lblocks++] = 1 + II - tbs;
7492       tbs              = 1 + II;
7493     }
7494   }
7495   if (rank < size - 1) {
7496     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7497     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7498   }
7499 
7500   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7501   if (!set || !flag) PetscCall(MatDestroy(&AA));
7502   PetscCall(MatDestroy(&A));
7503 
7504   PetscCall(PetscNew(&edata));
7505   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7506   edata->n = lblocks;
7507   /* create IS needed for extracting blocks from the original matrix */
7508   PetscCall(PetscMalloc1(lblocks, &edata->is));
7509   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7510 
7511   /* Create the resulting inverse matrix structure with preallocation information */
7512   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7513   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7514   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7515   PetscCall(MatSetType(edata->C, MATAIJ));
7516 
7517   /* Communicate the start and end of each row, from each block to the correct rank */
7518   /* TODO: Use PetscSF instead of VecScatter */
7519   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7520   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7521   PetscCall(VecGetArrayWrite(seq, &seqv));
7522   for (PetscInt i = 0; i < lblocks; i++) {
7523     for (PetscInt j = 0; j < sizes[i]; j++) {
7524       seqv[cnt]     = starts[i];
7525       seqv[cnt + 1] = starts[i] + sizes[i];
7526       cnt += 2;
7527     }
7528   }
7529   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7530   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7531   sc -= cnt;
7532   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7533   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7534   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7535   PetscCall(ISDestroy(&isglobal));
7536   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7537   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7538   PetscCall(VecScatterDestroy(&scatter));
7539   PetscCall(VecDestroy(&seq));
7540   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7541   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7542   PetscCall(VecGetArrayRead(par, &parv));
7543   cnt = 0;
7544   PetscCall(MatGetSize(mat, NULL, &n));
7545   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7546     PetscInt start, end, d = 0, od = 0;
7547 
7548     start = (PetscInt)PetscRealPart(parv[cnt]);
7549     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7550     cnt += 2;
7551 
7552     if (start < cstart) {
7553       od += cstart - start + n - cend;
7554       d += cend - cstart;
7555     } else if (start < cend) {
7556       od += n - cend;
7557       d += cend - start;
7558     } else od += n - start;
7559     if (end <= cstart) {
7560       od -= cstart - end + n - cend;
7561       d -= cend - cstart;
7562     } else if (end < cend) {
7563       od -= n - cend;
7564       d -= cend - end;
7565     } else od -= n - end;
7566 
7567     odiag[i] = od;
7568     diag[i]  = d;
7569   }
7570   PetscCall(VecRestoreArrayRead(par, &parv));
7571   PetscCall(VecDestroy(&par));
7572   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7573   PetscCall(PetscFree2(diag, odiag));
7574   PetscCall(PetscFree2(sizes, starts));
7575 
7576   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7577   PetscCall(PetscContainerSetPointer(container, edata));
7578   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7579   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7580   PetscCall(PetscObjectDereference((PetscObject)container));
7581   PetscFunctionReturn(PETSC_SUCCESS);
7582 }
7583 
7584 /*@
7585   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7586 
7587   Collective on A
7588 
7589   Input Parameters:
7590 . A - the matrix
7591 
7592   Output Parameters:
7593 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7594 
7595   Note:
7596      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7597 
7598   Level: advanced
7599 
7600 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7601 @*/
7602 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7603 {
7604   PetscContainer   container;
7605   EnvelopeData    *edata;
7606   PetscObjectState nonzerostate;
7607 
7608   PetscFunctionBegin;
7609   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7610   if (!container) {
7611     PetscCall(MatComputeVariableBlockEnvelope(A));
7612     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7613   }
7614   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7615   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7616   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7617   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7618 
7619   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7620   *C = edata->C;
7621 
7622   for (PetscInt i = 0; i < edata->n; i++) {
7623     Mat          D;
7624     PetscScalar *dvalues;
7625 
7626     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7627     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7628     PetscCall(MatSeqDenseInvert(D));
7629     PetscCall(MatDenseGetArray(D, &dvalues));
7630     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7631     PetscCall(MatDestroy(&D));
7632   }
7633   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7634   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7635   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7636   PetscFunctionReturn(PETSC_SUCCESS);
7637 }
7638 
7639 /*@
7640    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7641 
7642    Logically Collective
7643 
7644    Input Parameters:
7645 +  mat - the matrix
7646 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7647 -  bsizes - the block sizes
7648 
7649    Notes:
7650     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7651 
7652     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.
7653 
7654    Level: intermediate
7655 
7656 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7657           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7658 @*/
7659 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7660 {
7661   PetscInt i, ncnt = 0, nlocal;
7662 
7663   PetscFunctionBegin;
7664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7665   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7666   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7667   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7668   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);
7669   PetscCall(PetscFree(mat->bsizes));
7670   mat->nblocks = nblocks;
7671   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7672   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7673   PetscFunctionReturn(PETSC_SUCCESS);
7674 }
7675 
7676 /*@C
7677    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7678 
7679    Logically Collective; No Fortran Support
7680 
7681    Input Parameter:
7682 .  mat - the matrix
7683 
7684    Output Parameters:
7685 +  nblocks - the number of blocks on this process
7686 -  bsizes - the block sizes
7687 
7688    Level: intermediate
7689 
7690 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7691 @*/
7692 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7693 {
7694   PetscFunctionBegin;
7695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7696   *nblocks = mat->nblocks;
7697   *bsizes  = mat->bsizes;
7698   PetscFunctionReturn(PETSC_SUCCESS);
7699 }
7700 
7701 /*@
7702    MatSetBlockSizes - Sets the matrix block row and column sizes.
7703 
7704    Logically Collective
7705 
7706    Input Parameters:
7707 +  mat - the matrix
7708 .  rbs - row block size
7709 -  cbs - column block size
7710 
7711    Notes:
7712     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7713     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7714     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7715 
7716     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7717     are compatible with the matrix local sizes.
7718 
7719     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7720 
7721    Level: intermediate
7722 
7723 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7724 @*/
7725 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7726 {
7727   PetscFunctionBegin;
7728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7729   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7730   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7731   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7732   if (mat->rmap->refcnt) {
7733     ISLocalToGlobalMapping l2g  = NULL;
7734     PetscLayout            nmap = NULL;
7735 
7736     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7737     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7738     PetscCall(PetscLayoutDestroy(&mat->rmap));
7739     mat->rmap          = nmap;
7740     mat->rmap->mapping = l2g;
7741   }
7742   if (mat->cmap->refcnt) {
7743     ISLocalToGlobalMapping l2g  = NULL;
7744     PetscLayout            nmap = NULL;
7745 
7746     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7747     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7748     PetscCall(PetscLayoutDestroy(&mat->cmap));
7749     mat->cmap          = nmap;
7750     mat->cmap->mapping = l2g;
7751   }
7752   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7753   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7754   PetscFunctionReturn(PETSC_SUCCESS);
7755 }
7756 
7757 /*@
7758    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7759 
7760    Logically Collective
7761 
7762    Input Parameters:
7763 +  mat - the matrix
7764 .  fromRow - matrix from which to copy row block size
7765 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7766 
7767    Level: developer
7768 
7769 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7770 @*/
7771 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7772 {
7773   PetscFunctionBegin;
7774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7775   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7776   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7777   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7778   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7779   PetscFunctionReturn(PETSC_SUCCESS);
7780 }
7781 
7782 /*@
7783    MatResidual - Default routine to calculate the residual r = b - Ax
7784 
7785    Collective
7786 
7787    Input Parameters:
7788 +  mat - the matrix
7789 .  b   - the right-hand-side
7790 -  x   - the approximate solution
7791 
7792    Output Parameter:
7793 .  r - location to store the residual
7794 
7795    Level: developer
7796 
7797 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7798 @*/
7799 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7800 {
7801   PetscFunctionBegin;
7802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7803   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7804   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7805   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7806   PetscValidType(mat, 1);
7807   MatCheckPreallocated(mat, 1);
7808   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7809   if (!mat->ops->residual) {
7810     PetscCall(MatMult(mat, x, r));
7811     PetscCall(VecAYPX(r, -1.0, b));
7812   } else {
7813     PetscUseTypeMethod(mat, residual, b, x, r);
7814   }
7815   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7816   PetscFunctionReturn(PETSC_SUCCESS);
7817 }
7818 
7819 /*MC
7820     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7821 
7822     Synopsis:
7823     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7824 
7825     Not Collective
7826 
7827     Input Parameters:
7828 +   A - the matrix
7829 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7830 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7831 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7832                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7833                  always used.
7834 
7835     Output Parameters:
7836 +   n - number of local rows in the (possibly compressed) matrix
7837 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7838 .   ja - the column indices
7839 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7840            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7841 
7842     Level: developer
7843 
7844     Note:
7845     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7846 
7847 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7848 M*/
7849 
7850 /*MC
7851     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7852 
7853     Synopsis:
7854     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7855 
7856     Not Collective
7857 
7858     Input Parameters:
7859 +   A - the  matrix
7860 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7861 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7862     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7863                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7864                  always used.
7865 .   n - number of local rows in the (possibly compressed) matrix
7866 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7867 .   ja - the column indices
7868 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7869            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7870 
7871     Level: developer
7872 
7873 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7874 M*/
7875 
7876 /*@C
7877     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7878 
7879    Collective
7880 
7881     Input Parameters:
7882 +   mat - the matrix
7883 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7884 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7885 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7886                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7887                  always used.
7888 
7889     Output Parameters:
7890 +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7891 .   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
7892 .   ja - the column indices, use NULL if not needed
7893 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7894            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7895 
7896     Level: developer
7897 
7898     Notes:
7899     You CANNOT change any of the ia[] or ja[] values.
7900 
7901     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7902 
7903     Fortran Notes:
7904     In Fortran use
7905 .vb
7906     PetscInt, pointer :: ia(:),ja(:)
7907     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7908     ! Access the ith and jth entries via ia(i) and ja(j)
7909 .ve
7910    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7911 
7912 .seealso: `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7913 @*/
7914 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7915 {
7916   PetscFunctionBegin;
7917   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7918   PetscValidType(mat, 1);
7919   if (n) PetscValidIntPointer(n, 5);
7920   if (ia) PetscValidPointer(ia, 6);
7921   if (ja) PetscValidPointer(ja, 7);
7922   if (done) PetscValidBoolPointer(done, 8);
7923   MatCheckPreallocated(mat, 1);
7924   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7925   else {
7926     if (done) *done = PETSC_TRUE;
7927     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7928     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7929     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7930   }
7931   PetscFunctionReturn(PETSC_SUCCESS);
7932 }
7933 
7934 /*@C
7935     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7936 
7937     Collective
7938 
7939     Input Parameters:
7940 +   mat - the matrix
7941 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7942 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7943                 symmetrized
7944 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7945                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7946                  always used.
7947 .   n - number of columns in the (possibly compressed) matrix
7948 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7949 -   ja - the row indices
7950 
7951     Output Parameters:
7952 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7953 
7954     Level: developer
7955 
7956 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7957 @*/
7958 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7959 {
7960   PetscFunctionBegin;
7961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7962   PetscValidType(mat, 1);
7963   PetscValidIntPointer(n, 5);
7964   if (ia) PetscValidPointer(ia, 6);
7965   if (ja) PetscValidPointer(ja, 7);
7966   PetscValidBoolPointer(done, 8);
7967   MatCheckPreallocated(mat, 1);
7968   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7969   else {
7970     *done = PETSC_TRUE;
7971     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7972   }
7973   PetscFunctionReturn(PETSC_SUCCESS);
7974 }
7975 
7976 /*@C
7977     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7978 
7979     Collective
7980 
7981     Input Parameters:
7982 +   mat - the matrix
7983 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7984 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7985 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7986                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7987                  always used.
7988 .   n - size of (possibly compressed) matrix
7989 .   ia - the row pointers
7990 -   ja - the column indices
7991 
7992     Output Parameters:
7993 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7994 
7995     Level: developer
7996 
7997     Note:
7998     This routine zeros out n, ia, and ja. This is to prevent accidental
7999     us of the array after it has been restored. If you pass NULL, it will
8000     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8001 
8002     Fortran Note:
8003    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8004 
8005 .seealso: `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8006 @*/
8007 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8008 {
8009   PetscFunctionBegin;
8010   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8011   PetscValidType(mat, 1);
8012   if (ia) PetscValidPointer(ia, 6);
8013   if (ja) PetscValidPointer(ja, 7);
8014   if (done) PetscValidBoolPointer(done, 8);
8015   MatCheckPreallocated(mat, 1);
8016 
8017   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8018   else {
8019     if (done) *done = PETSC_TRUE;
8020     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8021     if (n) *n = 0;
8022     if (ia) *ia = NULL;
8023     if (ja) *ja = NULL;
8024   }
8025   PetscFunctionReturn(PETSC_SUCCESS);
8026 }
8027 
8028 /*@C
8029     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8030 
8031     Collective on Mat
8032 
8033     Input Parameters:
8034 +   mat - the matrix
8035 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8036 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8037 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8038                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8039                  always used.
8040 
8041     Output Parameters:
8042 +   n - size of (possibly compressed) matrix
8043 .   ia - the column pointers
8044 .   ja - the row indices
8045 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8046 
8047     Level: developer
8048 
8049 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8050 @*/
8051 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8052 {
8053   PetscFunctionBegin;
8054   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8055   PetscValidType(mat, 1);
8056   if (ia) PetscValidPointer(ia, 6);
8057   if (ja) PetscValidPointer(ja, 7);
8058   PetscValidBoolPointer(done, 8);
8059   MatCheckPreallocated(mat, 1);
8060 
8061   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8062   else {
8063     *done = PETSC_TRUE;
8064     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8065     if (n) *n = 0;
8066     if (ia) *ia = NULL;
8067     if (ja) *ja = NULL;
8068   }
8069   PetscFunctionReturn(PETSC_SUCCESS);
8070 }
8071 
8072 /*@C
8073     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8074 
8075     Collective
8076 
8077     Input Parameters:
8078 +   mat - the matrix
8079 .   ncolors - max color value
8080 .   n   - number of entries in colorarray
8081 -   colorarray - array indicating color for each column
8082 
8083     Output Parameters:
8084 .   iscoloring - coloring generated using colorarray information
8085 
8086     Level: developer
8087 
8088 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
8089 @*/
8090 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8091 {
8092   PetscFunctionBegin;
8093   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8094   PetscValidType(mat, 1);
8095   PetscValidIntPointer(colorarray, 4);
8096   PetscValidPointer(iscoloring, 5);
8097   MatCheckPreallocated(mat, 1);
8098 
8099   if (!mat->ops->coloringpatch) {
8100     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8101   } else {
8102     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8103   }
8104   PetscFunctionReturn(PETSC_SUCCESS);
8105 }
8106 
8107 /*@
8108    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8109 
8110    Logically Collective
8111 
8112    Input Parameter:
8113 .  mat - the factored matrix to be reset
8114 
8115    Notes:
8116    This routine should be used only with factored matrices formed by in-place
8117    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8118    format).  This option can save memory, for example, when solving nonlinear
8119    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8120    ILU(0) preconditioner.
8121 
8122    Note that one can specify in-place ILU(0) factorization by calling
8123 .vb
8124      PCType(pc,PCILU);
8125      PCFactorSeUseInPlace(pc);
8126 .ve
8127    or by using the options -pc_type ilu -pc_factor_in_place
8128 
8129    In-place factorization ILU(0) can also be used as a local
8130    solver for the blocks within the block Jacobi or additive Schwarz
8131    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8132    for details on setting local solver options.
8133 
8134    Most users should employ the `KSP` interface for linear solvers
8135    instead of working directly with matrix algebra routines such as this.
8136    See, e.g., `KSPCreate()`.
8137 
8138    Level: developer
8139 
8140 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8141 @*/
8142 PetscErrorCode MatSetUnfactored(Mat mat)
8143 {
8144   PetscFunctionBegin;
8145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8146   PetscValidType(mat, 1);
8147   MatCheckPreallocated(mat, 1);
8148   mat->factortype = MAT_FACTOR_NONE;
8149   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8150   PetscUseTypeMethod(mat, setunfactored);
8151   PetscFunctionReturn(PETSC_SUCCESS);
8152 }
8153 
8154 /*MC
8155     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8156 
8157     Synopsis:
8158     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8159 
8160     Not collective
8161 
8162     Input Parameter:
8163 .   x - matrix
8164 
8165     Output Parameters:
8166 +   xx_v - the Fortran pointer to the array
8167 -   ierr - error code
8168 
8169     Example of Usage:
8170 .vb
8171       PetscScalar, pointer xx_v(:,:)
8172       ....
8173       call MatDenseGetArrayF90(x,xx_v,ierr)
8174       a = xx_v(3)
8175       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8176 .ve
8177 
8178     Level: advanced
8179 
8180 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8181 
8182 M*/
8183 
8184 /*MC
8185     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8186     accessed with `MatDenseGetArrayF90()`.
8187 
8188     Synopsis:
8189     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8190 
8191     Not collective
8192 
8193     Input Parameters:
8194 +   x - matrix
8195 -   xx_v - the Fortran90 pointer to the array
8196 
8197     Output Parameter:
8198 .   ierr - error code
8199 
8200     Example of Usage:
8201 .vb
8202        PetscScalar, pointer xx_v(:,:)
8203        ....
8204        call MatDenseGetArrayF90(x,xx_v,ierr)
8205        a = xx_v(3)
8206        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8207 .ve
8208 
8209     Level: advanced
8210 
8211 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8212 
8213 M*/
8214 
8215 /*MC
8216     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8217 
8218     Synopsis:
8219     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8220 
8221     Not collective
8222 
8223     Input Parameter:
8224 .   x - matrix
8225 
8226     Output Parameters:
8227 +   xx_v - the Fortran pointer to the array
8228 -   ierr - error code
8229 
8230     Example of Usage:
8231 .vb
8232       PetscScalar, pointer xx_v(:)
8233       ....
8234       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8235       a = xx_v(3)
8236       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8237 .ve
8238 
8239     Level: advanced
8240 
8241 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8242 
8243 M*/
8244 
8245 /*MC
8246     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8247     accessed with `MatSeqAIJGetArrayF90()`.
8248 
8249     Synopsis:
8250     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8251 
8252     Not collective
8253 
8254     Input Parameters:
8255 +   x - matrix
8256 -   xx_v - the Fortran90 pointer to the array
8257 
8258     Output Parameter:
8259 .   ierr - error code
8260 
8261     Example of Usage:
8262 .vb
8263        PetscScalar, pointer xx_v(:)
8264        ....
8265        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8266        a = xx_v(3)
8267        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8268 .ve
8269 
8270     Level: advanced
8271 
8272 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8273 
8274 M*/
8275 
8276 /*@
8277     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8278                       as the original matrix.
8279 
8280     Collective
8281 
8282     Input Parameters:
8283 +   mat - the original matrix
8284 .   isrow - parallel IS containing the rows this processor should obtain
8285 .   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.
8286 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8287 
8288     Output Parameter:
8289 .   newmat - the new submatrix, of the same type as the old
8290 
8291     Level: advanced
8292 
8293     Notes:
8294     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8295 
8296     Some matrix types place restrictions on the row and column indices, such
8297     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;
8298     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8299 
8300     The index sets may not have duplicate entries.
8301 
8302       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8303    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8304    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8305    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8306    you are finished using it.
8307 
8308     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8309     the input matrix.
8310 
8311     If iscol is NULL then all columns are obtained (not supported in Fortran).
8312 
8313    Example usage:
8314    Consider the following 8x8 matrix with 34 non-zero values, that is
8315    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8316    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8317    as follows:
8318 
8319 .vb
8320             1  2  0  |  0  3  0  |  0  4
8321     Proc0   0  5  6  |  7  0  0  |  8  0
8322             9  0 10  | 11  0  0  | 12  0
8323     -------------------------------------
8324            13  0 14  | 15 16 17  |  0  0
8325     Proc1   0 18  0  | 19 20 21  |  0  0
8326             0  0  0  | 22 23  0  | 24  0
8327     -------------------------------------
8328     Proc2  25 26 27  |  0  0 28  | 29  0
8329            30  0  0  | 31 32 33  |  0 34
8330 .ve
8331 
8332     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8333 
8334 .vb
8335             2  0  |  0  3  0  |  0
8336     Proc0   5  6  |  7  0  0  |  8
8337     -------------------------------
8338     Proc1  18  0  | 19 20 21  |  0
8339     -------------------------------
8340     Proc2  26 27  |  0  0 28  | 29
8341             0  0  | 31 32 33  |  0
8342 .ve
8343 
8344 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8345 @*/
8346 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8347 {
8348   PetscMPIInt size;
8349   Mat        *local;
8350   IS          iscoltmp;
8351   PetscBool   flg;
8352 
8353   PetscFunctionBegin;
8354   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8355   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8356   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8357   PetscValidPointer(newmat, 5);
8358   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8359   PetscValidType(mat, 1);
8360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8361   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8362 
8363   MatCheckPreallocated(mat, 1);
8364   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8365 
8366   if (!iscol || isrow == iscol) {
8367     PetscBool   stride;
8368     PetscMPIInt grabentirematrix = 0, grab;
8369     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8370     if (stride) {
8371       PetscInt first, step, n, rstart, rend;
8372       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8373       if (step == 1) {
8374         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8375         if (rstart == first) {
8376           PetscCall(ISGetLocalSize(isrow, &n));
8377           if (n == rend - rstart) grabentirematrix = 1;
8378         }
8379       }
8380     }
8381     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8382     if (grab) {
8383       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8384       if (cll == MAT_INITIAL_MATRIX) {
8385         *newmat = mat;
8386         PetscCall(PetscObjectReference((PetscObject)mat));
8387       }
8388       PetscFunctionReturn(PETSC_SUCCESS);
8389     }
8390   }
8391 
8392   if (!iscol) {
8393     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8394   } else {
8395     iscoltmp = iscol;
8396   }
8397 
8398   /* if original matrix is on just one processor then use submatrix generated */
8399   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8400     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8401     goto setproperties;
8402   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8403     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8404     *newmat = *local;
8405     PetscCall(PetscFree(local));
8406     goto setproperties;
8407   } else if (!mat->ops->createsubmatrix) {
8408     /* Create a new matrix type that implements the operation using the full matrix */
8409     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8410     switch (cll) {
8411     case MAT_INITIAL_MATRIX:
8412       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8413       break;
8414     case MAT_REUSE_MATRIX:
8415       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8416       break;
8417     default:
8418       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8419     }
8420     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8421     goto setproperties;
8422   }
8423 
8424   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8425   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8426   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8427 
8428 setproperties:
8429   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8430   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8431   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8432   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8433   PetscFunctionReturn(PETSC_SUCCESS);
8434 }
8435 
8436 /*@
8437    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8438 
8439    Not Collective
8440 
8441    Input Parameters:
8442 +  A - the matrix we wish to propagate options from
8443 -  B - the matrix we wish to propagate options to
8444 
8445    Level: beginner
8446 
8447    Note:
8448    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8449 
8450 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8451 @*/
8452 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8453 {
8454   PetscFunctionBegin;
8455   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8456   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8457   B->symmetry_eternal            = A->symmetry_eternal;
8458   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8459   B->symmetric                   = A->symmetric;
8460   B->structurally_symmetric      = A->structurally_symmetric;
8461   B->spd                         = A->spd;
8462   B->hermitian                   = A->hermitian;
8463   PetscFunctionReturn(PETSC_SUCCESS);
8464 }
8465 
8466 /*@
8467    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8468    used during the assembly process to store values that belong to
8469    other processors.
8470 
8471    Not Collective
8472 
8473    Input Parameters:
8474 +  mat   - the matrix
8475 .  size  - the initial size of the stash.
8476 -  bsize - the initial size of the block-stash(if used).
8477 
8478    Options Database Keys:
8479 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8480 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8481 
8482    Level: intermediate
8483 
8484    Notes:
8485      The block-stash is used for values set with `MatSetValuesBlocked()` while
8486      the stash is used for values set with `MatSetValues()`
8487 
8488      Run with the option -info and look for output of the form
8489      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8490      to determine the appropriate value, MM, to use for size and
8491      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8492      to determine the value, BMM to use for bsize
8493 
8494 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8495 @*/
8496 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8497 {
8498   PetscFunctionBegin;
8499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8500   PetscValidType(mat, 1);
8501   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8502   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8503   PetscFunctionReturn(PETSC_SUCCESS);
8504 }
8505 
8506 /*@
8507    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8508      the matrix
8509 
8510    Neighbor-wise Collective
8511 
8512    Input Parameters:
8513 +  mat   - the matrix
8514 .  x,y - the vectors
8515 -  w - where the result is stored
8516 
8517    Level: intermediate
8518 
8519    Notes:
8520     w may be the same vector as y.
8521 
8522     This allows one to use either the restriction or interpolation (its transpose)
8523     matrix to do the interpolation
8524 
8525 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8526 @*/
8527 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8528 {
8529   PetscInt M, N, Ny;
8530 
8531   PetscFunctionBegin;
8532   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8533   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8534   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8535   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8536   PetscCall(MatGetSize(A, &M, &N));
8537   PetscCall(VecGetSize(y, &Ny));
8538   if (M == Ny) {
8539     PetscCall(MatMultAdd(A, x, y, w));
8540   } else {
8541     PetscCall(MatMultTransposeAdd(A, x, y, w));
8542   }
8543   PetscFunctionReturn(PETSC_SUCCESS);
8544 }
8545 
8546 /*@
8547    MatInterpolate - y = A*x or A'*x depending on the shape of
8548      the matrix
8549 
8550    Neighbor-wise Collective
8551 
8552    Input Parameters:
8553 +  mat   - the matrix
8554 -  x,y - the vectors
8555 
8556    Level: intermediate
8557 
8558    Note:
8559     This allows one to use either the restriction or interpolation (its transpose)
8560     matrix to do the interpolation
8561 
8562 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8563 @*/
8564 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8565 {
8566   PetscInt M, N, Ny;
8567 
8568   PetscFunctionBegin;
8569   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8570   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8571   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8572   PetscCall(MatGetSize(A, &M, &N));
8573   PetscCall(VecGetSize(y, &Ny));
8574   if (M == Ny) {
8575     PetscCall(MatMult(A, x, y));
8576   } else {
8577     PetscCall(MatMultTranspose(A, x, y));
8578   }
8579   PetscFunctionReturn(PETSC_SUCCESS);
8580 }
8581 
8582 /*@
8583    MatRestrict - y = A*x or A'*x
8584 
8585    Neighbor-wise Collective on Mat
8586 
8587    Input Parameters:
8588 +  mat   - the matrix
8589 -  x,y - the vectors
8590 
8591    Level: intermediate
8592 
8593    Note:
8594     This allows one to use either the restriction or interpolation (its transpose)
8595     matrix to do the restriction
8596 
8597 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8598 @*/
8599 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8600 {
8601   PetscInt M, N, Ny;
8602 
8603   PetscFunctionBegin;
8604   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8605   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8606   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8607   PetscCall(MatGetSize(A, &M, &N));
8608   PetscCall(VecGetSize(y, &Ny));
8609   if (M == Ny) {
8610     PetscCall(MatMult(A, x, y));
8611   } else {
8612     PetscCall(MatMultTranspose(A, x, y));
8613   }
8614   PetscFunctionReturn(PETSC_SUCCESS);
8615 }
8616 
8617 /*@
8618    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8619 
8620    Neighbor-wise Collective on Mat
8621 
8622    Input Parameters:
8623 +  mat   - the matrix
8624 -  w, x - the input dense matrices
8625 
8626    Output Parameters:
8627 .  y - the output dense matrix
8628 
8629    Level: intermediate
8630 
8631    Note:
8632     This allows one to use either the restriction or interpolation (its transpose)
8633     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8634     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8635 
8636 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8637 @*/
8638 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8639 {
8640   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8641   PetscBool trans = PETSC_TRUE;
8642   MatReuse  reuse = MAT_INITIAL_MATRIX;
8643 
8644   PetscFunctionBegin;
8645   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8646   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8647   PetscValidType(x, 2);
8648   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8649   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8650   PetscCall(MatGetSize(A, &M, &N));
8651   PetscCall(MatGetSize(x, &Mx, &Nx));
8652   if (N == Mx) trans = PETSC_FALSE;
8653   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);
8654   Mo = trans ? N : M;
8655   if (*y) {
8656     PetscCall(MatGetSize(*y, &My, &Ny));
8657     if (Mo == My && Nx == Ny) {
8658       reuse = MAT_REUSE_MATRIX;
8659     } else {
8660       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);
8661       PetscCall(MatDestroy(y));
8662     }
8663   }
8664 
8665   if (w && *y == w) { /* this is to minimize changes in PCMG */
8666     PetscBool flg;
8667 
8668     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8669     if (w) {
8670       PetscInt My, Ny, Mw, Nw;
8671 
8672       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8673       PetscCall(MatGetSize(*y, &My, &Ny));
8674       PetscCall(MatGetSize(w, &Mw, &Nw));
8675       if (!flg || My != Mw || Ny != Nw) w = NULL;
8676     }
8677     if (!w) {
8678       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8679       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8680       PetscCall(PetscObjectDereference((PetscObject)w));
8681     } else {
8682       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8683     }
8684   }
8685   if (!trans) {
8686     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8687   } else {
8688     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8689   }
8690   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8691   PetscFunctionReturn(PETSC_SUCCESS);
8692 }
8693 
8694 /*@
8695    MatMatInterpolate - Y = A*X or A'*X
8696 
8697    Neighbor-wise Collective on Mat
8698 
8699    Input Parameters:
8700 +  mat   - the matrix
8701 -  x - the input dense matrix
8702 
8703    Output Parameters:
8704 .  y - the output dense matrix
8705 
8706    Level: intermediate
8707 
8708    Note:
8709     This allows one to use either the restriction or interpolation (its transpose)
8710     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8711     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8712 
8713 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8714 @*/
8715 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8716 {
8717   PetscFunctionBegin;
8718   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8719   PetscFunctionReturn(PETSC_SUCCESS);
8720 }
8721 
8722 /*@
8723    MatMatRestrict - Y = A*X or A'*X
8724 
8725    Neighbor-wise Collective on Mat
8726 
8727    Input Parameters:
8728 +  mat   - the matrix
8729 -  x - the input dense matrix
8730 
8731    Output Parameters:
8732 .  y - the output dense matrix
8733 
8734    Level: intermediate
8735 
8736    Note:
8737     This allows one to use either the restriction or interpolation (its transpose)
8738     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8739     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8740 
8741 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8742 @*/
8743 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8744 {
8745   PetscFunctionBegin;
8746   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8747   PetscFunctionReturn(PETSC_SUCCESS);
8748 }
8749 
8750 /*@
8751    MatGetNullSpace - retrieves the null space of a matrix.
8752 
8753    Logically Collective
8754 
8755    Input Parameters:
8756 +  mat - the matrix
8757 -  nullsp - the null space object
8758 
8759    Level: developer
8760 
8761 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8762 @*/
8763 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8764 {
8765   PetscFunctionBegin;
8766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8767   PetscValidPointer(nullsp, 2);
8768   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8769   PetscFunctionReturn(PETSC_SUCCESS);
8770 }
8771 
8772 /*@
8773    MatSetNullSpace - attaches a null space to a matrix.
8774 
8775    Logically Collective
8776 
8777    Input Parameters:
8778 +  mat - the matrix
8779 -  nullsp - the null space object
8780 
8781    Level: advanced
8782 
8783    Notes:
8784       This null space is used by the `KSP` linear solvers to solve singular systems.
8785 
8786       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
8787 
8788       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
8789       to zero but the linear system will still be solved in a least squares sense.
8790 
8791       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8792    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).
8793    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
8794    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
8795    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).
8796    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8797 
8798     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8799     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8800     routine also automatically calls `MatSetTransposeNullSpace()`.
8801 
8802     The user should call `MatNullSpaceDestroy()`.
8803 
8804 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8805           `KSPSetPCSide()`
8806 @*/
8807 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8808 {
8809   PetscFunctionBegin;
8810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8811   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8812   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8813   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8814   mat->nullsp = nullsp;
8815   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8816   PetscFunctionReturn(PETSC_SUCCESS);
8817 }
8818 
8819 /*@
8820    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8821 
8822    Logically Collective
8823 
8824    Input Parameters:
8825 +  mat - the matrix
8826 -  nullsp - the null space object
8827 
8828    Level: developer
8829 
8830 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8831 @*/
8832 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8833 {
8834   PetscFunctionBegin;
8835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8836   PetscValidType(mat, 1);
8837   PetscValidPointer(nullsp, 2);
8838   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8839   PetscFunctionReturn(PETSC_SUCCESS);
8840 }
8841 
8842 /*@
8843    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8844 
8845    Logically Collective
8846 
8847    Input Parameters:
8848 +  mat - the matrix
8849 -  nullsp - the null space object
8850 
8851    Level: advanced
8852 
8853    Notes:
8854    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8855 
8856    See `MatSetNullSpace()`
8857 
8858 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8859 @*/
8860 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8861 {
8862   PetscFunctionBegin;
8863   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8864   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8865   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8866   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8867   mat->transnullsp = nullsp;
8868   PetscFunctionReturn(PETSC_SUCCESS);
8869 }
8870 
8871 /*@
8872    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8873         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8874 
8875    Logically Collective
8876 
8877    Input Parameters:
8878 +  mat - the matrix
8879 -  nullsp - the null space object
8880 
8881    Level: advanced
8882 
8883    Notes:
8884    Overwrites any previous near null space that may have been attached
8885 
8886    You can remove the null space by calling this routine with an nullsp of NULL
8887 
8888 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8889 @*/
8890 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8891 {
8892   PetscFunctionBegin;
8893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8894   PetscValidType(mat, 1);
8895   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8896   MatCheckPreallocated(mat, 1);
8897   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8898   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8899   mat->nearnullsp = nullsp;
8900   PetscFunctionReturn(PETSC_SUCCESS);
8901 }
8902 
8903 /*@
8904    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8905 
8906    Not Collective
8907 
8908    Input Parameter:
8909 .  mat - the matrix
8910 
8911    Output Parameter:
8912 .  nullsp - the null space object, NULL if not set
8913 
8914    Level: advanced
8915 
8916 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8917 @*/
8918 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8919 {
8920   PetscFunctionBegin;
8921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8922   PetscValidType(mat, 1);
8923   PetscValidPointer(nullsp, 2);
8924   MatCheckPreallocated(mat, 1);
8925   *nullsp = mat->nearnullsp;
8926   PetscFunctionReturn(PETSC_SUCCESS);
8927 }
8928 
8929 /*@C
8930    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8931 
8932    Collective
8933 
8934    Input Parameters:
8935 +  mat - the matrix
8936 .  row - row/column permutation
8937 .  fill - expected fill factor >= 1.0
8938 -  level - level of fill, for ICC(k)
8939 
8940    Notes:
8941    Probably really in-place only when level of fill is zero, otherwise allocates
8942    new space to store factored matrix and deletes previous memory.
8943 
8944    Most users should employ the `KSP` interface for linear solvers
8945    instead of working directly with matrix algebra routines such as this.
8946    See, e.g., `KSPCreate()`.
8947 
8948    Level: developer
8949 
8950    Developer Note:
8951    The Fortran interface is not autogenerated as the
8952    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8953 
8954 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8955 @*/
8956 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8957 {
8958   PetscFunctionBegin;
8959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8960   PetscValidType(mat, 1);
8961   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8962   PetscValidPointer(info, 3);
8963   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8964   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8965   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8966   MatCheckPreallocated(mat, 1);
8967   PetscUseTypeMethod(mat, iccfactor, row, info);
8968   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8969   PetscFunctionReturn(PETSC_SUCCESS);
8970 }
8971 
8972 /*@
8973    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8974          ghosted ones.
8975 
8976    Not Collective
8977 
8978    Input Parameters:
8979 +  mat - the matrix
8980 -  diag - the diagonal values, including ghost ones
8981 
8982    Level: developer
8983 
8984    Notes:
8985     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8986 
8987     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8988 
8989 .seealso: `MatDiagonalScale()`
8990 @*/
8991 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8992 {
8993   PetscMPIInt size;
8994 
8995   PetscFunctionBegin;
8996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8997   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8998   PetscValidType(mat, 1);
8999 
9000   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9001   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9002   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9003   if (size == 1) {
9004     PetscInt n, m;
9005     PetscCall(VecGetSize(diag, &n));
9006     PetscCall(MatGetSize(mat, NULL, &m));
9007     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9008     PetscCall(MatDiagonalScale(mat, NULL, diag));
9009   } else {
9010     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9011   }
9012   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9013   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9014   PetscFunctionReturn(PETSC_SUCCESS);
9015 }
9016 
9017 /*@
9018    MatGetInertia - Gets the inertia from a factored matrix
9019 
9020    Collective
9021 
9022    Input Parameter:
9023 .  mat - the matrix
9024 
9025    Output Parameters:
9026 +   nneg - number of negative eigenvalues
9027 .   nzero - number of zero eigenvalues
9028 -   npos - number of positive eigenvalues
9029 
9030    Level: advanced
9031 
9032    Note:
9033     Matrix must have been factored by `MatCholeskyFactor()`
9034 
9035 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
9036 @*/
9037 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9038 {
9039   PetscFunctionBegin;
9040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9041   PetscValidType(mat, 1);
9042   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9043   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9044   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9045   PetscFunctionReturn(PETSC_SUCCESS);
9046 }
9047 
9048 /* ----------------------------------------------------------------*/
9049 /*@C
9050    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9051 
9052    Neighbor-wise Collective
9053 
9054    Input Parameters:
9055 +  mat - the factored matrix obtained with `MatGetFactor()`
9056 -  b - the right-hand-side vectors
9057 
9058    Output Parameter:
9059 .  x - the result vectors
9060 
9061    Note:
9062    The vectors b and x cannot be the same.  I.e., one cannot
9063    call `MatSolves`(A,x,x).
9064 
9065    Level: developer
9066 
9067 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9068 @*/
9069 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9070 {
9071   PetscFunctionBegin;
9072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9073   PetscValidType(mat, 1);
9074   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9075   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9076   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9077 
9078   MatCheckPreallocated(mat, 1);
9079   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9080   PetscUseTypeMethod(mat, solves, b, x);
9081   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9082   PetscFunctionReturn(PETSC_SUCCESS);
9083 }
9084 
9085 /*@
9086    MatIsSymmetric - Test whether a matrix is symmetric
9087 
9088    Collective
9089 
9090    Input Parameters:
9091 +  A - the matrix to test
9092 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9093 
9094    Output Parameters:
9095 .  flg - the result
9096 
9097    Notes:
9098     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9099 
9100     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9101 
9102     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9103     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9104 
9105    Level: intermediate
9106 
9107 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9108           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9109 @*/
9110 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9111 {
9112   PetscFunctionBegin;
9113   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9114   PetscValidBoolPointer(flg, 3);
9115 
9116   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9117   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9118   else {
9119     if (!A->ops->issymmetric) {
9120       MatType mattype;
9121       PetscCall(MatGetType(A, &mattype));
9122       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9123     }
9124     PetscUseTypeMethod(A, issymmetric, tol, flg);
9125     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9126   }
9127   PetscFunctionReturn(PETSC_SUCCESS);
9128 }
9129 
9130 /*@
9131    MatIsHermitian - Test whether a matrix is Hermitian
9132 
9133    Collective on Mat
9134 
9135    Input Parameters:
9136 +  A - the matrix to test
9137 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9138 
9139    Output Parameters:
9140 .  flg - the result
9141 
9142    Level: intermediate
9143 
9144    Notes:
9145     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9146 
9147     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9148 
9149     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9150     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9151 
9152 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9153           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9154 @*/
9155 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9156 {
9157   PetscFunctionBegin;
9158   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9159   PetscValidBoolPointer(flg, 3);
9160 
9161   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9162   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9163   else {
9164     if (!A->ops->ishermitian) {
9165       MatType mattype;
9166       PetscCall(MatGetType(A, &mattype));
9167       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9168     }
9169     PetscUseTypeMethod(A, ishermitian, tol, flg);
9170     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9171   }
9172   PetscFunctionReturn(PETSC_SUCCESS);
9173 }
9174 
9175 /*@
9176    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9177 
9178    Not Collective
9179 
9180    Input Parameter:
9181 .  A - the matrix to check
9182 
9183    Output Parameters:
9184 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9185 -  flg - the result (only valid if set is `PETSC_TRUE`)
9186 
9187    Level: advanced
9188 
9189    Notes:
9190    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9191    if you want it explicitly checked
9192 
9193     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9194     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9195 
9196 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9197 @*/
9198 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9199 {
9200   PetscFunctionBegin;
9201   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9202   PetscValidBoolPointer(set, 2);
9203   PetscValidBoolPointer(flg, 3);
9204   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9205     *set = PETSC_TRUE;
9206     *flg = PetscBool3ToBool(A->symmetric);
9207   } else {
9208     *set = PETSC_FALSE;
9209   }
9210   PetscFunctionReturn(PETSC_SUCCESS);
9211 }
9212 
9213 /*@
9214    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9215 
9216    Not Collective
9217 
9218    Input Parameter:
9219 .  A - the matrix to check
9220 
9221    Output Parameters:
9222 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9223 -  flg - the result (only valid if set is `PETSC_TRUE`)
9224 
9225    Level: advanced
9226 
9227    Notes:
9228    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9229 
9230    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9231    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9232 
9233 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9234 @*/
9235 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9236 {
9237   PetscFunctionBegin;
9238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9239   PetscValidBoolPointer(set, 2);
9240   PetscValidBoolPointer(flg, 3);
9241   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9242     *set = PETSC_TRUE;
9243     *flg = PetscBool3ToBool(A->spd);
9244   } else {
9245     *set = PETSC_FALSE;
9246   }
9247   PetscFunctionReturn(PETSC_SUCCESS);
9248 }
9249 
9250 /*@
9251    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9252 
9253    Not Collective
9254 
9255    Input Parameter:
9256 .  A - the matrix to check
9257 
9258    Output Parameters:
9259 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9260 -  flg - the result (only valid if set is `PETSC_TRUE`)
9261 
9262    Level: advanced
9263 
9264    Notes:
9265    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9266    if you want it explicitly checked
9267 
9268    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9269    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9270 
9271 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9272 @*/
9273 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9274 {
9275   PetscFunctionBegin;
9276   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9277   PetscValidBoolPointer(set, 2);
9278   PetscValidBoolPointer(flg, 3);
9279   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9280     *set = PETSC_TRUE;
9281     *flg = PetscBool3ToBool(A->hermitian);
9282   } else {
9283     *set = PETSC_FALSE;
9284   }
9285   PetscFunctionReturn(PETSC_SUCCESS);
9286 }
9287 
9288 /*@
9289    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9290 
9291    Collective on Mat
9292 
9293    Input Parameter:
9294 .  A - the matrix to test
9295 
9296    Output Parameters:
9297 .  flg - the result
9298 
9299    Notes:
9300    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9301 
9302    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
9303    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9304 
9305    Level: intermediate
9306 
9307 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9308 @*/
9309 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9310 {
9311   PetscFunctionBegin;
9312   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9313   PetscValidBoolPointer(flg, 2);
9314   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9315     *flg = PetscBool3ToBool(A->structurally_symmetric);
9316   } else {
9317     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9318     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9319   }
9320   PetscFunctionReturn(PETSC_SUCCESS);
9321 }
9322 
9323 /*@
9324    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9325 
9326    Not Collective
9327 
9328    Input Parameter:
9329 .  A - the matrix to check
9330 
9331    Output Parameters:
9332 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9333 -  flg - the result (only valid if set is PETSC_TRUE)
9334 
9335    Level: advanced
9336 
9337    Notes:
9338    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
9339    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9340 
9341    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9342 
9343 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9344 @*/
9345 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9346 {
9347   PetscFunctionBegin;
9348   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9349   PetscValidBoolPointer(set, 2);
9350   PetscValidBoolPointer(flg, 3);
9351   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9352     *set = PETSC_TRUE;
9353     *flg = PetscBool3ToBool(A->structurally_symmetric);
9354   } else {
9355     *set = PETSC_FALSE;
9356   }
9357   PetscFunctionReturn(PETSC_SUCCESS);
9358 }
9359 
9360 /*@
9361    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9362        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9363 
9364     Not collective
9365 
9366    Input Parameter:
9367 .   mat - the matrix
9368 
9369    Output Parameters:
9370 +   nstash   - the size of the stash
9371 .   reallocs - the number of additional mallocs incurred.
9372 .   bnstash   - the size of the block stash
9373 -   breallocs - the number of additional mallocs incurred.in the block stash
9374 
9375    Level: advanced
9376 
9377 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9378 @*/
9379 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9380 {
9381   PetscFunctionBegin;
9382   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9383   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9384   PetscFunctionReturn(PETSC_SUCCESS);
9385 }
9386 
9387 /*@C
9388    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9389    parallel layout, `PetscLayout` for rows and columns
9390 
9391    Collective
9392 
9393    Input Parameter:
9394 .  mat - the matrix
9395 
9396    Output Parameters:
9397 +   right - (optional) vector that the matrix can be multiplied against
9398 -   left - (optional) vector that the matrix vector product can be stored in
9399 
9400    Notes:
9401     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()`.
9402 
9403     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9404 
9405   Level: advanced
9406 
9407 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9408 @*/
9409 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9410 {
9411   PetscFunctionBegin;
9412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9413   PetscValidType(mat, 1);
9414   if (mat->ops->getvecs) {
9415     PetscUseTypeMethod(mat, getvecs, right, left);
9416   } else {
9417     PetscInt rbs, cbs;
9418     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9419     if (right) {
9420       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9421       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9422       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9423       PetscCall(VecSetBlockSize(*right, cbs));
9424       PetscCall(VecSetType(*right, mat->defaultvectype));
9425 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9426       if (mat->boundtocpu && mat->bindingpropagates) {
9427         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9428         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9429       }
9430 #endif
9431       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9432     }
9433     if (left) {
9434       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9435       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9436       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9437       PetscCall(VecSetBlockSize(*left, rbs));
9438       PetscCall(VecSetType(*left, mat->defaultvectype));
9439 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9440       if (mat->boundtocpu && mat->bindingpropagates) {
9441         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9442         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9443       }
9444 #endif
9445       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9446     }
9447   }
9448   PetscFunctionReturn(PETSC_SUCCESS);
9449 }
9450 
9451 /*@C
9452    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9453      with default values.
9454 
9455    Not Collective
9456 
9457    Input Parameters:
9458 .    info - the `MatFactorInfo` data structure
9459 
9460    Notes:
9461     The solvers are generally used through the `KSP` and `PC` objects, for example
9462           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9463 
9464     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9465 
9466    Level: developer
9467 
9468    Developer Note:
9469    The Fortran interface is not autogenerated as the
9470    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9471 
9472 .seealso: `MatGetFactor()`, `MatFactorInfo`
9473 @*/
9474 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9475 {
9476   PetscFunctionBegin;
9477   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9478   PetscFunctionReturn(PETSC_SUCCESS);
9479 }
9480 
9481 /*@
9482    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9483 
9484    Collective
9485 
9486    Input Parameters:
9487 +  mat - the factored matrix
9488 -  is - the index set defining the Schur indices (0-based)
9489 
9490    Notes:
9491     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9492 
9493    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9494 
9495    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9496 
9497    Level: advanced
9498 
9499 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9500           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9501 
9502 @*/
9503 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9504 {
9505   PetscErrorCode (*f)(Mat, IS);
9506 
9507   PetscFunctionBegin;
9508   PetscValidType(mat, 1);
9509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9510   PetscValidType(is, 2);
9511   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9512   PetscCheckSameComm(mat, 1, is, 2);
9513   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9514   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9515   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9516   PetscCall(MatDestroy(&mat->schur));
9517   PetscCall((*f)(mat, is));
9518   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9519   PetscFunctionReturn(PETSC_SUCCESS);
9520 }
9521 
9522 /*@
9523   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9524 
9525    Logically Collective
9526 
9527    Input Parameters:
9528 +  F - the factored matrix obtained by calling `MatGetFactor()`
9529 .  S - location where to return the Schur complement, can be NULL
9530 -  status - the status of the Schur complement matrix, can be NULL
9531 
9532    Notes:
9533    You must call `MatFactorSetSchurIS()` before calling this routine.
9534 
9535    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9536 
9537    The routine provides a copy of the Schur matrix stored within the solver data structures.
9538    The caller must destroy the object when it is no longer needed.
9539    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9540 
9541    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)
9542 
9543    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9544 
9545    Developer Note:
9546     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9547    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9548 
9549    Level: advanced
9550 
9551 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9552 @*/
9553 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9554 {
9555   PetscFunctionBegin;
9556   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9557   if (S) PetscValidPointer(S, 2);
9558   if (status) PetscValidPointer(status, 3);
9559   if (S) {
9560     PetscErrorCode (*f)(Mat, Mat *);
9561 
9562     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9563     if (f) {
9564       PetscCall((*f)(F, S));
9565     } else {
9566       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9567     }
9568   }
9569   if (status) *status = F->schur_status;
9570   PetscFunctionReturn(PETSC_SUCCESS);
9571 }
9572 
9573 /*@
9574   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9575 
9576    Logically Collective
9577 
9578    Input Parameters:
9579 +  F - the factored matrix obtained by calling `MatGetFactor()`
9580 .  *S - location where to return the Schur complement, can be NULL
9581 -  status - the status of the Schur complement matrix, can be NULL
9582 
9583    Notes:
9584    You must call `MatFactorSetSchurIS()` before calling this routine.
9585 
9586    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9587 
9588    The routine returns a the Schur Complement stored within the data strutures of the solver.
9589 
9590    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9591 
9592    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9593 
9594    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9595 
9596    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9597 
9598    Level: advanced
9599 
9600 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9601 @*/
9602 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9603 {
9604   PetscFunctionBegin;
9605   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9606   if (S) PetscValidPointer(S, 2);
9607   if (status) PetscValidPointer(status, 3);
9608   if (S) *S = F->schur;
9609   if (status) *status = F->schur_status;
9610   PetscFunctionReturn(PETSC_SUCCESS);
9611 }
9612 
9613 /*@
9614   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9615 
9616    Logically Collective
9617 
9618    Input Parameters:
9619 +  F - the factored matrix obtained by calling `MatGetFactor()`
9620 .  *S - location where the Schur complement is stored
9621 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9622 
9623    Level: advanced
9624 
9625 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9626 @*/
9627 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9628 {
9629   PetscFunctionBegin;
9630   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9631   if (S) {
9632     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9633     *S = NULL;
9634   }
9635   F->schur_status = status;
9636   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9637   PetscFunctionReturn(PETSC_SUCCESS);
9638 }
9639 
9640 /*@
9641   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9642 
9643    Logically Collective
9644 
9645    Input Parameters:
9646 +  F - the factored matrix obtained by calling `MatGetFactor()`
9647 .  rhs - location where the right hand side of the Schur complement system is stored
9648 -  sol - location where the solution of the Schur complement system has to be returned
9649 
9650    Notes:
9651    The sizes of the vectors should match the size of the Schur complement
9652 
9653    Must be called after `MatFactorSetSchurIS()`
9654 
9655    Level: advanced
9656 
9657 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9658 @*/
9659 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9660 {
9661   PetscFunctionBegin;
9662   PetscValidType(F, 1);
9663   PetscValidType(rhs, 2);
9664   PetscValidType(sol, 3);
9665   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9666   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9667   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9668   PetscCheckSameComm(F, 1, rhs, 2);
9669   PetscCheckSameComm(F, 1, sol, 3);
9670   PetscCall(MatFactorFactorizeSchurComplement(F));
9671   switch (F->schur_status) {
9672   case MAT_FACTOR_SCHUR_FACTORED:
9673     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9674     break;
9675   case MAT_FACTOR_SCHUR_INVERTED:
9676     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9677     break;
9678   default:
9679     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9680   }
9681   PetscFunctionReturn(PETSC_SUCCESS);
9682 }
9683 
9684 /*@
9685   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9686 
9687    Logically Collective
9688 
9689    Input Parameters:
9690 +  F - the factored matrix obtained by calling `MatGetFactor()`
9691 .  rhs - location where the right hand side of the Schur complement system is stored
9692 -  sol - location where the solution of the Schur complement system has to be returned
9693 
9694    Notes:
9695    The sizes of the vectors should match the size of the Schur complement
9696 
9697    Must be called after `MatFactorSetSchurIS()`
9698 
9699    Level: advanced
9700 
9701 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9702 @*/
9703 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9704 {
9705   PetscFunctionBegin;
9706   PetscValidType(F, 1);
9707   PetscValidType(rhs, 2);
9708   PetscValidType(sol, 3);
9709   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9710   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9711   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9712   PetscCheckSameComm(F, 1, rhs, 2);
9713   PetscCheckSameComm(F, 1, sol, 3);
9714   PetscCall(MatFactorFactorizeSchurComplement(F));
9715   switch (F->schur_status) {
9716   case MAT_FACTOR_SCHUR_FACTORED:
9717     PetscCall(MatSolve(F->schur, rhs, sol));
9718     break;
9719   case MAT_FACTOR_SCHUR_INVERTED:
9720     PetscCall(MatMult(F->schur, rhs, sol));
9721     break;
9722   default:
9723     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9724   }
9725   PetscFunctionReturn(PETSC_SUCCESS);
9726 }
9727 
9728 /*@
9729   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9730 
9731    Logically Collective on F
9732 
9733    Input Parameters:
9734 .  F - the factored matrix obtained by calling `MatGetFactor()`
9735 
9736    Notes:
9737     Must be called after `MatFactorSetSchurIS()`.
9738 
9739    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9740 
9741    Level: advanced
9742 
9743 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9744 @*/
9745 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9746 {
9747   PetscFunctionBegin;
9748   PetscValidType(F, 1);
9749   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9750   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9751   PetscCall(MatFactorFactorizeSchurComplement(F));
9752   PetscCall(MatFactorInvertSchurComplement_Private(F));
9753   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9754   PetscFunctionReturn(PETSC_SUCCESS);
9755 }
9756 
9757 /*@
9758   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9759 
9760    Logically Collective
9761 
9762    Input Parameters:
9763 .  F - the factored matrix obtained by calling `MatGetFactor()`
9764 
9765    Note:
9766     Must be called after `MatFactorSetSchurIS()`
9767 
9768    Level: advanced
9769 
9770 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9771 @*/
9772 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9773 {
9774   PetscFunctionBegin;
9775   PetscValidType(F, 1);
9776   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9777   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9778   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9779   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9780   PetscFunctionReturn(PETSC_SUCCESS);
9781 }
9782 
9783 /*@
9784    MatPtAP - Creates the matrix product C = P^T * A * P
9785 
9786    Neighbor-wise Collective on A
9787 
9788    Input Parameters:
9789 +  A - the matrix
9790 .  P - the projection matrix
9791 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9792 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9793           if the result is a dense matrix this is irrelevant
9794 
9795    Output Parameters:
9796 .  C - the product matrix
9797 
9798    Notes:
9799    C will be created and must be destroyed by the user with `MatDestroy()`.
9800 
9801    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9802 
9803    Developer Note:
9804    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9805 
9806    Level: intermediate
9807 
9808 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9809 @*/
9810 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9811 {
9812   PetscFunctionBegin;
9813   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9814   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9815 
9816   if (scall == MAT_INITIAL_MATRIX) {
9817     PetscCall(MatProductCreate(A, P, NULL, C));
9818     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9819     PetscCall(MatProductSetAlgorithm(*C, "default"));
9820     PetscCall(MatProductSetFill(*C, fill));
9821 
9822     (*C)->product->api_user = PETSC_TRUE;
9823     PetscCall(MatProductSetFromOptions(*C));
9824     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);
9825     PetscCall(MatProductSymbolic(*C));
9826   } else { /* scall == MAT_REUSE_MATRIX */
9827     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9828   }
9829 
9830   PetscCall(MatProductNumeric(*C));
9831   (*C)->symmetric = A->symmetric;
9832   (*C)->spd       = A->spd;
9833   PetscFunctionReturn(PETSC_SUCCESS);
9834 }
9835 
9836 /*@
9837    MatRARt - Creates the matrix product C = R * A * R^T
9838 
9839    Neighbor-wise Collective on A
9840 
9841    Input Parameters:
9842 +  A - the matrix
9843 .  R - the projection matrix
9844 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9845 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9846           if the result is a dense matrix this is irrelevant
9847 
9848    Output Parameters:
9849 .  C - the product matrix
9850 
9851    Notes:
9852    C will be created and must be destroyed by the user with `MatDestroy()`.
9853 
9854    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9855 
9856    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9857    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9858    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9859    We recommend using MatPtAP().
9860 
9861    Level: intermediate
9862 
9863 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9864 @*/
9865 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9866 {
9867   PetscFunctionBegin;
9868   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9869   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9870 
9871   if (scall == MAT_INITIAL_MATRIX) {
9872     PetscCall(MatProductCreate(A, R, NULL, C));
9873     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9874     PetscCall(MatProductSetAlgorithm(*C, "default"));
9875     PetscCall(MatProductSetFill(*C, fill));
9876 
9877     (*C)->product->api_user = PETSC_TRUE;
9878     PetscCall(MatProductSetFromOptions(*C));
9879     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);
9880     PetscCall(MatProductSymbolic(*C));
9881   } else { /* scall == MAT_REUSE_MATRIX */
9882     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9883   }
9884 
9885   PetscCall(MatProductNumeric(*C));
9886   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9887   PetscFunctionReturn(PETSC_SUCCESS);
9888 }
9889 
9890 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9891 {
9892   PetscFunctionBegin;
9893   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9894 
9895   if (scall == MAT_INITIAL_MATRIX) {
9896     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9897     PetscCall(MatProductCreate(A, B, NULL, C));
9898     PetscCall(MatProductSetType(*C, ptype));
9899     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9900     PetscCall(MatProductSetFill(*C, fill));
9901 
9902     (*C)->product->api_user = PETSC_TRUE;
9903     PetscCall(MatProductSetFromOptions(*C));
9904     PetscCall(MatProductSymbolic(*C));
9905   } else { /* scall == MAT_REUSE_MATRIX */
9906     Mat_Product *product = (*C)->product;
9907     PetscBool    isdense;
9908 
9909     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9910     if (isdense && product && product->type != ptype) {
9911       PetscCall(MatProductClear(*C));
9912       product = NULL;
9913     }
9914     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9915     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9916       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9917       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9918       product           = (*C)->product;
9919       product->fill     = fill;
9920       product->api_user = PETSC_TRUE;
9921       product->clear    = PETSC_TRUE;
9922 
9923       PetscCall(MatProductSetType(*C, ptype));
9924       PetscCall(MatProductSetFromOptions(*C));
9925       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);
9926       PetscCall(MatProductSymbolic(*C));
9927     } else { /* user may change input matrices A or B when REUSE */
9928       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9929     }
9930   }
9931   PetscCall(MatProductNumeric(*C));
9932   PetscFunctionReturn(PETSC_SUCCESS);
9933 }
9934 
9935 /*@
9936    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9937 
9938    Neighbor-wise Collective on A
9939 
9940    Input Parameters:
9941 +  A - the left matrix
9942 .  B - the right matrix
9943 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9944 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9945           if the result is a dense matrix this is irrelevant
9946 
9947    Output Parameters:
9948 .  C - the product matrix
9949 
9950    Notes:
9951    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9952 
9953    `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
9954    call to this function with `MAT_INITIAL_MATRIX`.
9955 
9956    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9957 
9958    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`,
9959    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9960 
9961    Example of Usage:
9962 .vb
9963      MatProductCreate(A,B,NULL,&C);
9964      MatProductSetType(C,MATPRODUCT_AB);
9965      MatProductSymbolic(C);
9966      MatProductNumeric(C); // compute C=A * B
9967      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9968      MatProductNumeric(C);
9969      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9970      MatProductNumeric(C);
9971 .ve
9972 
9973    Level: intermediate
9974 
9975 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9976 @*/
9977 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
9978 {
9979   PetscFunctionBegin;
9980   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9981   PetscFunctionReturn(PETSC_SUCCESS);
9982 }
9983 
9984 /*@
9985    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9986 
9987    Neighbor-wise Collective on A
9988 
9989    Input Parameters:
9990 +  A - the left matrix
9991 .  B - the right matrix
9992 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9993 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9994 
9995    Output Parameters:
9996 .  C - the product matrix
9997 
9998    Notes:
9999    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10000 
10001    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10002 
10003    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10004    actually needed.
10005 
10006    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10007    and for pairs of `MATMPIDENSE` matrices.
10008 
10009    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10010 
10011    Options Database Keys:
10012 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10013               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10014               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10015 
10016    Level: intermediate
10017 
10018 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10019 @*/
10020 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10021 {
10022   PetscFunctionBegin;
10023   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10024   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10025   PetscFunctionReturn(PETSC_SUCCESS);
10026 }
10027 
10028 /*@
10029    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10030 
10031    Neighbor-wise Collective on A
10032 
10033    Input Parameters:
10034 +  A - the left matrix
10035 .  B - the right matrix
10036 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10037 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10038 
10039    Output Parameters:
10040 .  C - the product matrix
10041 
10042    Notes:
10043    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10044 
10045    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10046 
10047    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10048 
10049    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10050    actually needed.
10051 
10052    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10053    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10054 
10055    Level: intermediate
10056 
10057 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10058 @*/
10059 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10060 {
10061   PetscFunctionBegin;
10062   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10063   PetscFunctionReturn(PETSC_SUCCESS);
10064 }
10065 
10066 /*@
10067    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10068 
10069    Neighbor-wise Collective on A
10070 
10071    Input Parameters:
10072 +  A - the left matrix
10073 .  B - the middle matrix
10074 .  C - the right matrix
10075 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10076 -  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
10077           if the result is a dense matrix this is irrelevant
10078 
10079    Output Parameters:
10080 .  D - the product matrix
10081 
10082    Notes:
10083    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10084 
10085    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10086 
10087    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10088 
10089    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10090    actually needed.
10091 
10092    If you have many matrices with the same non-zero structure to multiply, you
10093    should use `MAT_REUSE_MATRIX` in all calls but the first
10094 
10095    Level: intermediate
10096 
10097 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10098 @*/
10099 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10100 {
10101   PetscFunctionBegin;
10102   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10103   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10104 
10105   if (scall == MAT_INITIAL_MATRIX) {
10106     PetscCall(MatProductCreate(A, B, C, D));
10107     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10108     PetscCall(MatProductSetAlgorithm(*D, "default"));
10109     PetscCall(MatProductSetFill(*D, fill));
10110 
10111     (*D)->product->api_user = PETSC_TRUE;
10112     PetscCall(MatProductSetFromOptions(*D));
10113     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,
10114                ((PetscObject)C)->type_name);
10115     PetscCall(MatProductSymbolic(*D));
10116   } else { /* user may change input matrices when REUSE */
10117     PetscCall(MatProductReplaceMats(A, B, C, *D));
10118   }
10119   PetscCall(MatProductNumeric(*D));
10120   PetscFunctionReturn(PETSC_SUCCESS);
10121 }
10122 
10123 /*@
10124    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10125 
10126    Collective
10127 
10128    Input Parameters:
10129 +  mat - the matrix
10130 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10131 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10132 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10133 
10134    Output Parameter:
10135 .  matredundant - redundant matrix
10136 
10137    Notes:
10138    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10139    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10140 
10141    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10142    calling it.
10143 
10144    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10145 
10146    Level: advanced
10147 
10148 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10149 @*/
10150 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10151 {
10152   MPI_Comm       comm;
10153   PetscMPIInt    size;
10154   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10155   Mat_Redundant *redund     = NULL;
10156   PetscSubcomm   psubcomm   = NULL;
10157   MPI_Comm       subcomm_in = subcomm;
10158   Mat           *matseq;
10159   IS             isrow, iscol;
10160   PetscBool      newsubcomm = PETSC_FALSE;
10161 
10162   PetscFunctionBegin;
10163   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10164   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10165     PetscValidPointer(*matredundant, 5);
10166     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10167   }
10168 
10169   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10170   if (size == 1 || nsubcomm == 1) {
10171     if (reuse == MAT_INITIAL_MATRIX) {
10172       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10173     } else {
10174       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");
10175       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10176     }
10177     PetscFunctionReturn(PETSC_SUCCESS);
10178   }
10179 
10180   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10181   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10182   MatCheckPreallocated(mat, 1);
10183 
10184   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10185   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10186     /* create psubcomm, then get subcomm */
10187     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10188     PetscCallMPI(MPI_Comm_size(comm, &size));
10189     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10190 
10191     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10192     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10193     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10194     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10195     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10196     newsubcomm = PETSC_TRUE;
10197     PetscCall(PetscSubcommDestroy(&psubcomm));
10198   }
10199 
10200   /* get isrow, iscol and a local sequential matrix matseq[0] */
10201   if (reuse == MAT_INITIAL_MATRIX) {
10202     mloc_sub = PETSC_DECIDE;
10203     nloc_sub = PETSC_DECIDE;
10204     if (bs < 1) {
10205       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10206       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10207     } else {
10208       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10209       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10210     }
10211     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10212     rstart = rend - mloc_sub;
10213     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10214     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10215   } else { /* reuse == MAT_REUSE_MATRIX */
10216     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");
10217     /* retrieve subcomm */
10218     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10219     redund = (*matredundant)->redundant;
10220     isrow  = redund->isrow;
10221     iscol  = redund->iscol;
10222     matseq = redund->matseq;
10223   }
10224   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10225 
10226   /* get matredundant over subcomm */
10227   if (reuse == MAT_INITIAL_MATRIX) {
10228     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10229 
10230     /* create a supporting struct and attach it to C for reuse */
10231     PetscCall(PetscNew(&redund));
10232     (*matredundant)->redundant = redund;
10233     redund->isrow              = isrow;
10234     redund->iscol              = iscol;
10235     redund->matseq             = matseq;
10236     if (newsubcomm) {
10237       redund->subcomm = subcomm;
10238     } else {
10239       redund->subcomm = MPI_COMM_NULL;
10240     }
10241   } else {
10242     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10243   }
10244 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10245   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10246     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10247     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10248   }
10249 #endif
10250   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10251   PetscFunctionReturn(PETSC_SUCCESS);
10252 }
10253 
10254 /*@C
10255    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10256    a given `Mat`. Each submatrix can span multiple procs.
10257 
10258    Collective
10259 
10260    Input Parameters:
10261 +  mat - the matrix
10262 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
10263 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10264 
10265    Output Parameter:
10266 .  subMat - 'parallel submatrices each spans a given subcomm
10267 
10268   Notes:
10269   The submatrix partition across processors is dictated by 'subComm' a
10270   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
10271   is not restriced to be grouped with consecutive original ranks.
10272 
10273   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
10274   map directly to the layout of the original matrix [wrt the local
10275   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10276   into the 'DiagonalMat' of the subMat, hence it is used directly from
10277   the subMat. However the offDiagMat looses some columns - and this is
10278   reconstructed with `MatSetValues()`
10279 
10280   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10281 
10282   Level: advanced
10283 
10284 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10285 @*/
10286 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10287 {
10288   PetscMPIInt commsize, subCommSize;
10289 
10290   PetscFunctionBegin;
10291   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10292   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10293   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10294 
10295   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");
10296   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10297   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10298   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10299   PetscFunctionReturn(PETSC_SUCCESS);
10300 }
10301 
10302 /*@
10303    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10304 
10305    Not Collective
10306 
10307    Input Parameters:
10308 +  mat - matrix to extract local submatrix from
10309 .  isrow - local row indices for submatrix
10310 -  iscol - local column indices for submatrix
10311 
10312    Output Parameter:
10313 .  submat - the submatrix
10314 
10315    Level: intermediate
10316 
10317    Notes:
10318    The submat should be returned with `MatRestoreLocalSubMatrix()`.
10319 
10320    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
10321    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
10322 
10323    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
10324    `MatSetValuesBlockedLocal()` will also be implemented.
10325 
10326    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10327    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
10328 
10329 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10330 @*/
10331 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10332 {
10333   PetscFunctionBegin;
10334   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10335   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10336   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10337   PetscCheckSameComm(isrow, 2, iscol, 3);
10338   PetscValidPointer(submat, 4);
10339   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10340 
10341   if (mat->ops->getlocalsubmatrix) {
10342     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10343   } else {
10344     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10345   }
10346   PetscFunctionReturn(PETSC_SUCCESS);
10347 }
10348 
10349 /*@
10350    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10351 
10352    Not Collective
10353 
10354    Input Parameters:
10355 +  mat - matrix to extract local submatrix from
10356 .  isrow - local row indices for submatrix
10357 .  iscol - local column indices for submatrix
10358 -  submat - the submatrix
10359 
10360    Level: intermediate
10361 
10362 .seealso: `MatGetLocalSubMatrix()`
10363 @*/
10364 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10365 {
10366   PetscFunctionBegin;
10367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10368   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10369   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10370   PetscCheckSameComm(isrow, 2, iscol, 3);
10371   PetscValidPointer(submat, 4);
10372   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10373 
10374   if (mat->ops->restorelocalsubmatrix) {
10375     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10376   } else {
10377     PetscCall(MatDestroy(submat));
10378   }
10379   *submat = NULL;
10380   PetscFunctionReturn(PETSC_SUCCESS);
10381 }
10382 
10383 /* --------------------------------------------------------*/
10384 /*@
10385    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10386 
10387    Collective
10388 
10389    Input Parameter:
10390 .  mat - the matrix
10391 
10392    Output Parameter:
10393 .  is - if any rows have zero diagonals this contains the list of them
10394 
10395    Level: developer
10396 
10397 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10398 @*/
10399 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10400 {
10401   PetscFunctionBegin;
10402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10403   PetscValidType(mat, 1);
10404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10406 
10407   if (!mat->ops->findzerodiagonals) {
10408     Vec                diag;
10409     const PetscScalar *a;
10410     PetscInt          *rows;
10411     PetscInt           rStart, rEnd, r, nrow = 0;
10412 
10413     PetscCall(MatCreateVecs(mat, &diag, NULL));
10414     PetscCall(MatGetDiagonal(mat, diag));
10415     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10416     PetscCall(VecGetArrayRead(diag, &a));
10417     for (r = 0; r < rEnd - rStart; ++r)
10418       if (a[r] == 0.0) ++nrow;
10419     PetscCall(PetscMalloc1(nrow, &rows));
10420     nrow = 0;
10421     for (r = 0; r < rEnd - rStart; ++r)
10422       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10423     PetscCall(VecRestoreArrayRead(diag, &a));
10424     PetscCall(VecDestroy(&diag));
10425     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10426   } else {
10427     PetscUseTypeMethod(mat, findzerodiagonals, is);
10428   }
10429   PetscFunctionReturn(PETSC_SUCCESS);
10430 }
10431 
10432 /*@
10433    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10434 
10435    Collective
10436 
10437    Input Parameter:
10438 .  mat - the matrix
10439 
10440    Output Parameter:
10441 .  is - contains the list of rows with off block diagonal entries
10442 
10443    Level: developer
10444 
10445 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10446 @*/
10447 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10448 {
10449   PetscFunctionBegin;
10450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10451   PetscValidType(mat, 1);
10452   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10453   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10454 
10455   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10456   PetscFunctionReturn(PETSC_SUCCESS);
10457 }
10458 
10459 /*@C
10460   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10461 
10462   Collective; No Fortran Support
10463 
10464   Input Parameters:
10465 . mat - the matrix
10466 
10467   Output Parameters:
10468 . values - the block inverses in column major order (FORTRAN-like)
10469 
10470   Level: advanced
10471 
10472    Notes:
10473    The size of the blocks is determined by the block size of the matrix.
10474 
10475    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10476 
10477    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10478 
10479 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10480 @*/
10481 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10482 {
10483   PetscFunctionBegin;
10484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10485   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10486   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10487   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10488   PetscFunctionReturn(PETSC_SUCCESS);
10489 }
10490 
10491 /*@C
10492   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10493 
10494   Collective; No Fortran Support
10495 
10496   Input Parameters:
10497 + mat - the matrix
10498 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10499 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10500 
10501   Output Parameters:
10502 . values - the block inverses in column major order (FORTRAN-like)
10503 
10504   Level: advanced
10505 
10506   Notes:
10507   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10508 
10509   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10510 
10511 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10512 @*/
10513 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10514 {
10515   PetscFunctionBegin;
10516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10517   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10518   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10519   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10520   PetscFunctionReturn(PETSC_SUCCESS);
10521 }
10522 
10523 /*@
10524   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10525 
10526   Collective on Mat
10527 
10528   Input Parameters:
10529 + A - the matrix
10530 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10531 
10532   Note:
10533   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10534 
10535   Level: advanced
10536 
10537 .seealso: `MatInvertBlockDiagonal()`
10538 @*/
10539 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10540 {
10541   const PetscScalar *vals;
10542   PetscInt          *dnnz;
10543   PetscInt           m, rstart, rend, bs, i, j;
10544 
10545   PetscFunctionBegin;
10546   PetscCall(MatInvertBlockDiagonal(A, &vals));
10547   PetscCall(MatGetBlockSize(A, &bs));
10548   PetscCall(MatGetLocalSize(A, &m, NULL));
10549   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10550   PetscCall(PetscMalloc1(m / bs, &dnnz));
10551   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10552   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10553   PetscCall(PetscFree(dnnz));
10554   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10555   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10556   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10557   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10558   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10559   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10560   PetscFunctionReturn(PETSC_SUCCESS);
10561 }
10562 
10563 /*@C
10564     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10565     via `MatTransposeColoringCreate()`.
10566 
10567     Collective on c
10568 
10569     Input Parameter:
10570 .   c - coloring context
10571 
10572     Level: intermediate
10573 
10574 .seealso: `MatTransposeColoringCreate()`
10575 @*/
10576 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10577 {
10578   MatTransposeColoring matcolor = *c;
10579 
10580   PetscFunctionBegin;
10581   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10582   if (--((PetscObject)matcolor)->refct > 0) {
10583     matcolor = NULL;
10584     PetscFunctionReturn(PETSC_SUCCESS);
10585   }
10586 
10587   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10588   PetscCall(PetscFree(matcolor->rows));
10589   PetscCall(PetscFree(matcolor->den2sp));
10590   PetscCall(PetscFree(matcolor->colorforcol));
10591   PetscCall(PetscFree(matcolor->columns));
10592   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10593   PetscCall(PetscHeaderDestroy(c));
10594   PetscFunctionReturn(PETSC_SUCCESS);
10595 }
10596 
10597 /*@C
10598     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10599     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10600     `MatTransposeColoring` to sparse B.
10601 
10602     Collective on coloring
10603 
10604     Input Parameters:
10605 +   B - sparse matrix B
10606 .   Btdense - symbolic dense matrix B^T
10607 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10608 
10609     Output Parameter:
10610 .   Btdense - dense matrix B^T
10611 
10612     Level: developer
10613 
10614     Note:
10615     These are used internally for some implementations of `MatRARt()`
10616 
10617 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10618 
10619 @*/
10620 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10621 {
10622   PetscFunctionBegin;
10623   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10624   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10625   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10626 
10627   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10628   PetscFunctionReturn(PETSC_SUCCESS);
10629 }
10630 
10631 /*@C
10632     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10633     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10634     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10635     Csp from Cden.
10636 
10637     Collective
10638 
10639     Input Parameters:
10640 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10641 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10642 
10643     Output Parameter:
10644 .   Csp - sparse matrix
10645 
10646     Level: developer
10647 
10648     Note:
10649     These are used internally for some implementations of `MatRARt()`
10650 
10651 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10652 
10653 @*/
10654 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10655 {
10656   PetscFunctionBegin;
10657   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10658   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10659   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10660 
10661   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10662   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10663   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10664   PetscFunctionReturn(PETSC_SUCCESS);
10665 }
10666 
10667 /*@C
10668    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10669 
10670    Collective
10671 
10672    Input Parameters:
10673 +  mat - the matrix product C
10674 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10675 
10676     Output Parameter:
10677 .   color - the new coloring context
10678 
10679     Level: intermediate
10680 
10681 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10682           `MatTransColoringApplyDenToSp()`
10683 @*/
10684 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10685 {
10686   MatTransposeColoring c;
10687   MPI_Comm             comm;
10688 
10689   PetscFunctionBegin;
10690   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10691   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10692   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10693 
10694   c->ctype = iscoloring->ctype;
10695   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10696 
10697   *color = c;
10698   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10699   PetscFunctionReturn(PETSC_SUCCESS);
10700 }
10701 
10702 /*@
10703       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10704         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10705         same, otherwise it will be larger
10706 
10707      Not Collective
10708 
10709   Input Parameter:
10710 .    A  - the matrix
10711 
10712   Output Parameter:
10713 .    state - the current state
10714 
10715   Notes:
10716     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10717          different matrices
10718 
10719     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10720 
10721     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10722 
10723   Level: intermediate
10724 
10725 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10726 @*/
10727 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10728 {
10729   PetscFunctionBegin;
10730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10731   *state = mat->nonzerostate;
10732   PetscFunctionReturn(PETSC_SUCCESS);
10733 }
10734 
10735 /*@
10736       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10737                  matrices from each processor
10738 
10739     Collective
10740 
10741    Input Parameters:
10742 +    comm - the communicators the parallel matrix will live on
10743 .    seqmat - the input sequential matrices
10744 .    n - number of local columns (or `PETSC_DECIDE`)
10745 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10746 
10747    Output Parameter:
10748 .    mpimat - the parallel matrix generated
10749 
10750     Level: developer
10751 
10752    Note:
10753     The number of columns of the matrix in EACH processor MUST be the same.
10754 
10755 .seealso: `Mat`
10756 @*/
10757 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10758 {
10759   PetscMPIInt size;
10760 
10761   PetscFunctionBegin;
10762   PetscCallMPI(MPI_Comm_size(comm, &size));
10763   if (size == 1) {
10764     if (reuse == MAT_INITIAL_MATRIX) {
10765       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10766     } else {
10767       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10768     }
10769     PetscFunctionReturn(PETSC_SUCCESS);
10770   }
10771 
10772   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");
10773 
10774   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10775   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10776   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10777   PetscFunctionReturn(PETSC_SUCCESS);
10778 }
10779 
10780 /*@
10781      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10782 
10783     Collective on A
10784 
10785    Input Parameters:
10786 +    A   - the matrix to create subdomains from
10787 -    N   - requested number of subdomains
10788 
10789    Output Parameters:
10790 +    n   - number of subdomains resulting on this rank
10791 -    iss - `IS` list with indices of subdomains on this rank
10792 
10793     Level: advanced
10794 
10795     Note:
10796     The number of subdomains must be smaller than the communicator size
10797 
10798 .seealso: `Mat`, `IS`
10799 @*/
10800 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10801 {
10802   MPI_Comm    comm, subcomm;
10803   PetscMPIInt size, rank, color;
10804   PetscInt    rstart, rend, k;
10805 
10806   PetscFunctionBegin;
10807   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10808   PetscCallMPI(MPI_Comm_size(comm, &size));
10809   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10810   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);
10811   *n    = 1;
10812   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10813   color = rank / k;
10814   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10815   PetscCall(PetscMalloc1(1, iss));
10816   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10817   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10818   PetscCallMPI(MPI_Comm_free(&subcomm));
10819   PetscFunctionReturn(PETSC_SUCCESS);
10820 }
10821 
10822 /*@
10823    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10824 
10825    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10826    If they are not the same, uses `MatMatMatMult()`.
10827 
10828    Once the coarse grid problem is constructed, correct for interpolation operators
10829    that are not of full rank, which can legitimately happen in the case of non-nested
10830    geometric multigrid.
10831 
10832    Input Parameters:
10833 +  restrct - restriction operator
10834 .  dA - fine grid matrix
10835 .  interpolate - interpolation operator
10836 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10837 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10838 
10839    Output Parameters:
10840 .  A - the Galerkin coarse matrix
10841 
10842    Options Database Key:
10843 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10844 
10845    Level: developer
10846 
10847 .seealso: `MatPtAP()`, `MatMatMatMult()`
10848 @*/
10849 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10850 {
10851   IS  zerorows;
10852   Vec diag;
10853 
10854   PetscFunctionBegin;
10855   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10856   /* Construct the coarse grid matrix */
10857   if (interpolate == restrct) {
10858     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10859   } else {
10860     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10861   }
10862 
10863   /* If the interpolation matrix is not of full rank, A will have zero rows.
10864      This can legitimately happen in the case of non-nested geometric multigrid.
10865      In that event, we set the rows of the matrix to the rows of the identity,
10866      ignoring the equations (as the RHS will also be zero). */
10867 
10868   PetscCall(MatFindZeroRows(*A, &zerorows));
10869 
10870   if (zerorows != NULL) { /* if there are any zero rows */
10871     PetscCall(MatCreateVecs(*A, &diag, NULL));
10872     PetscCall(MatGetDiagonal(*A, diag));
10873     PetscCall(VecISSet(diag, zerorows, 1.0));
10874     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10875     PetscCall(VecDestroy(&diag));
10876     PetscCall(ISDestroy(&zerorows));
10877   }
10878   PetscFunctionReturn(PETSC_SUCCESS);
10879 }
10880 
10881 /*@C
10882     MatSetOperation - Allows user to set a matrix operation for any matrix type
10883 
10884    Logically Collective
10885 
10886     Input Parameters:
10887 +   mat - the matrix
10888 .   op - the name of the operation
10889 -   f - the function that provides the operation
10890 
10891    Level: developer
10892 
10893     Usage:
10894 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10895 $      PetscCall(MatCreateXXX(comm,...&A);
10896 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10897 
10898     Notes:
10899     See the file include/petscmat.h for a complete list of matrix
10900     operations, which all have the form MATOP_<OPERATION>, where
10901     <OPERATION> is the name (in all capital letters) of the
10902     user interface routine (e.g., MatMult() -> MATOP_MULT).
10903 
10904     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10905     sequence as the usual matrix interface routines, since they
10906     are intended to be accessed via the usual matrix interface
10907     routines, e.g.,
10908 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10909 
10910     In particular each function MUST return an error code of 0 on success and
10911     nonzero on failure.
10912 
10913     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10914 
10915 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10916 @*/
10917 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10918 {
10919   PetscFunctionBegin;
10920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10921   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10922   (((void (**)(void))mat->ops)[op]) = f;
10923   PetscFunctionReturn(PETSC_SUCCESS);
10924 }
10925 
10926 /*@C
10927     MatGetOperation - Gets a matrix operation for any matrix type.
10928 
10929     Not Collective
10930 
10931     Input Parameters:
10932 +   mat - the matrix
10933 -   op - the name of the operation
10934 
10935     Output Parameter:
10936 .   f - the function that provides the operation
10937 
10938     Level: developer
10939 
10940     Usage:
10941 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10942 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10943 
10944     Notes:
10945     See the file include/petscmat.h for a complete list of matrix
10946     operations, which all have the form MATOP_<OPERATION>, where
10947     <OPERATION> is the name (in all capital letters) of the
10948     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10949 
10950     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10951 
10952 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10953 @*/
10954 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
10955 {
10956   PetscFunctionBegin;
10957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10958   *f = (((void (**)(void))mat->ops)[op]);
10959   PetscFunctionReturn(PETSC_SUCCESS);
10960 }
10961 
10962 /*@
10963     MatHasOperation - Determines whether the given matrix supports the particular operation.
10964 
10965    Not Collective
10966 
10967    Input Parameters:
10968 +  mat - the matrix
10969 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10970 
10971    Output Parameter:
10972 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10973 
10974    Level: advanced
10975 
10976    Note:
10977    See the file include/petscmat.h for a complete list of matrix
10978    operations, which all have the form MATOP_<OPERATION>, where
10979    <OPERATION> is the name (in all capital letters) of the
10980    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10981 
10982 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10983 @*/
10984 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
10985 {
10986   PetscFunctionBegin;
10987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10988   PetscValidBoolPointer(has, 3);
10989   if (mat->ops->hasoperation) {
10990     PetscUseTypeMethod(mat, hasoperation, op, has);
10991   } else {
10992     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10993     else {
10994       *has = PETSC_FALSE;
10995       if (op == MATOP_CREATE_SUBMATRIX) {
10996         PetscMPIInt size;
10997 
10998         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10999         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11000       }
11001     }
11002   }
11003   PetscFunctionReturn(PETSC_SUCCESS);
11004 }
11005 
11006 /*@
11007     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11008 
11009    Collective
11010 
11011    Input Parameters:
11012 .  mat - the matrix
11013 
11014    Output Parameter:
11015 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11016 
11017    Level: beginner
11018 
11019 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11020 @*/
11021 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11022 {
11023   PetscFunctionBegin;
11024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11025   PetscValidType(mat, 1);
11026   PetscValidBoolPointer(cong, 2);
11027   if (!mat->rmap || !mat->cmap) {
11028     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11029     PetscFunctionReturn(PETSC_SUCCESS);
11030   }
11031   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11032     PetscCall(PetscLayoutSetUp(mat->rmap));
11033     PetscCall(PetscLayoutSetUp(mat->cmap));
11034     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11035     if (*cong) mat->congruentlayouts = 1;
11036     else mat->congruentlayouts = 0;
11037   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11038   PetscFunctionReturn(PETSC_SUCCESS);
11039 }
11040 
11041 PetscErrorCode MatSetInf(Mat A)
11042 {
11043   PetscFunctionBegin;
11044   PetscUseTypeMethod(A, setinf);
11045   PetscFunctionReturn(PETSC_SUCCESS);
11046 }
11047 
11048 /*@C
11049    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
11050    and possibly removes small values from the graph structure.
11051 
11052    Collective
11053 
11054    Input Parameters:
11055 +  A - the matrix
11056 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11057 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11058 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11059 
11060    Output Parameter:
11061 .  graph - the resulting graph
11062 
11063    Level: advanced
11064 
11065 .seealso: `MatCreate()`, `PCGAMG`
11066 @*/
11067 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11068 {
11069   PetscFunctionBegin;
11070   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11071   PetscValidType(A, 1);
11072   PetscValidLogicalCollectiveBool(A, scale, 3);
11073   PetscValidPointer(graph, 5);
11074   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11075   PetscFunctionReturn(PETSC_SUCCESS);
11076 }
11077 
11078 /*@
11079   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11080   meaning the same memory is used for the matrix, and no new memory is allocated.
11081 
11082   Collective on mat
11083 
11084   Input Parameter:
11085 . A - the matrix
11086 
11087   Output Parameter:
11088 . A - the matrix
11089 
11090   Level: intermediate
11091 
11092 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11093 @*/
11094 PetscErrorCode MatEliminateZeros(Mat A)
11095 {
11096   PetscFunctionBegin;
11097   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11098   PetscUseTypeMethod(A, eliminatezeros);
11099   PetscFunctionReturn(PETSC_SUCCESS);
11100 }
11101