xref: /petsc/src/mat/interface/matrix.c (revision 1593df67522d3430f90d31a96bd02a923730f389)
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.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameter:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
665 
666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameter:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameter:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses MatLoad()
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the sequential dense and AIJ
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary,hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto rank 0 and then shipped to its destination rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their PetscObject name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who's interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245 
1246    PETSc automatically does the byte swapping for
1247 machines that store the bytes reversed. Thus if you write your own binary
1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1249 and `PetscBinaryWrite()` to see how this may be done.
1250 
1251    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1252    Each processor's chunk is loaded independently by its owning rank.
1253    Multiple objects, both matrices and vectors, can be stored within the same file.
1254    They are looked up by their PetscObject name.
1255 
1256    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1257    by default the same structure and naming of the AIJ arrays and column count
1258    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1259 $    save example.mat A b -v7.3
1260    can be directly read by this routine (see Reference 1 for details).
1261 
1262    Depending on your MATLAB version, this format might be a default,
1263    otherwise you can set it as default in Preferences.
1264 
1265    Unless -nocompression flag is used to save the file in MATLAB,
1266    PETSc must be configured with ZLIB package.
1267 
1268    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1269 
1270    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1271 
1272    Corresponding `MatView()` is not yet implemented.
1273 
1274    The loaded matrix is actually a transpose of the original one in MATLAB,
1275    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1276    With this format, matrix is automatically transposed by PETSc,
1277    unless the matrix is marked as SPD or symmetric
1278    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1279 
1280    References:
1281 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1282 
1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1284  @*/
1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1286 {
1287   PetscBool flg;
1288 
1289   PetscFunctionBegin;
1290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1291   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1292 
1293   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1294 
1295   flg = PETSC_FALSE;
1296   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1297   if (flg) {
1298     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1300   }
1301   flg = PETSC_FALSE;
1302   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1303   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1304 
1305   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1306   PetscUseTypeMethod(mat, load, viewer);
1307   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1308   PetscFunctionReturn(PETSC_SUCCESS);
1309 }
1310 
1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1312 {
1313   Mat_Redundant *redund = *redundant;
1314 
1315   PetscFunctionBegin;
1316   if (redund) {
1317     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1318       PetscCall(ISDestroy(&redund->isrow));
1319       PetscCall(ISDestroy(&redund->iscol));
1320       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1321     } else {
1322       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1323       PetscCall(PetscFree(redund->sbuf_j));
1324       PetscCall(PetscFree(redund->sbuf_a));
1325       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1326         PetscCall(PetscFree(redund->rbuf_j[i]));
1327         PetscCall(PetscFree(redund->rbuf_a[i]));
1328       }
1329       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1330     }
1331 
1332     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1333     PetscCall(PetscFree(redund));
1334   }
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 /*@C
1339    MatDestroy - Frees space taken by a matrix.
1340 
1341    Collective
1342 
1343    Input Parameter:
1344 .  A - the matrix
1345 
1346    Level: beginner
1347 
1348    Developer Note:
1349    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1350    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1351    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1352    if changes are needed here.
1353 
1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1355 @*/
1356 PetscErrorCode MatDestroy(Mat *A)
1357 {
1358   PetscFunctionBegin;
1359   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1360   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1361   if (--((PetscObject)(*A))->refct > 0) {
1362     *A = NULL;
1363     PetscFunctionReturn(PETSC_SUCCESS);
1364   }
1365 
1366   /* if memory was published with SAWs then destroy it */
1367   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1368   PetscTryTypeMethod((*A), destroy);
1369 
1370   PetscCall(PetscFree((*A)->factorprefix));
1371   PetscCall(PetscFree((*A)->defaultvectype));
1372   PetscCall(PetscFree((*A)->defaultrandtype));
1373   PetscCall(PetscFree((*A)->bsizes));
1374   PetscCall(PetscFree((*A)->solvertype));
1375   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1376   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1377   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1378   PetscCall(MatProductClear(*A));
1379   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1382   PetscCall(MatDestroy(&(*A)->schur));
1383   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1384   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1385   PetscCall(PetscHeaderDestroy(A));
1386   PetscFunctionReturn(PETSC_SUCCESS);
1387 }
1388 
1389 /*@C
1390    MatSetValues - Inserts or adds a block of values into a matrix.
1391    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1392    MUST be called after all calls to `MatSetValues()` have been completed.
1393 
1394    Not Collective
1395 
1396    Input Parameters:
1397 +  mat - the matrix
1398 .  v - a logically two-dimensional array of values
1399 .  m - the number of rows
1400 .  idxm - the global indices of the rows
1401 .  n - the number of columns
1402 .  idxn - the global indices of the columns
1403 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1404 
1405    Level: beginner
1406 
1407    Notes:
1408    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1409 
1410    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1411    options cannot be mixed without intervening calls to the assembly
1412    routines.
1413 
1414    `MatSetValues()` uses 0-based row and column numbers in Fortran
1415    as well as in C.
1416 
1417    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1418    simply ignored. This allows easily inserting element stiffness matrices
1419    with homogeneous Dirchlet boundary conditions that you don't want represented
1420    in the matrix.
1421 
1422    Efficiency Alert:
1423    The routine `MatSetValuesBlocked()` may offer much better efficiency
1424    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1425 
1426    Developer Note:
1427    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1428    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1429 
1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1431           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1432 @*/
1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1434 {
1435   PetscFunctionBeginHot;
1436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1437   PetscValidType(mat, 1);
1438   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1439   PetscValidIntPointer(idxm, 3);
1440   PetscValidIntPointer(idxn, 5);
1441   MatCheckPreallocated(mat, 1);
1442 
1443   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1444   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1445 
1446   if (PetscDefined(USE_DEBUG)) {
1447     PetscInt i, j;
1448 
1449     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1450     for (i = 0; i < m; i++) {
1451       for (j = 0; j < n; j++) {
1452         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1453 #if defined(PETSC_USE_COMPLEX)
1454           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1455 #else
1456           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1457 #endif
1458       }
1459     }
1460     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1461     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1462   }
1463 
1464   if (mat->assembled) {
1465     mat->was_assembled = PETSC_TRUE;
1466     mat->assembled     = PETSC_FALSE;
1467   }
1468   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1469   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1470   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1471   PetscFunctionReturn(PETSC_SUCCESS);
1472 }
1473 
1474 /*@C
1475    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1476    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1477    MUST be called after all calls to `MatSetValues()` have been completed.
1478 
1479    Not Collective
1480 
1481    Input Parameters:
1482 +  mat - the matrix
1483 .  v - a logically two-dimensional array of values
1484 .  ism - the rows to provide
1485 .  isn - the columns to provide
1486 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1487 
1488    Level: beginner
1489 
1490    Notes:
1491    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1492 
1493    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1494    options cannot be mixed without intervening calls to the assembly
1495    routines.
1496 
1497    `MatSetValues()` uses 0-based row and column numbers in Fortran
1498    as well as in C.
1499 
1500    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1501    simply ignored. This allows easily inserting element stiffness matrices
1502    with homogeneous Dirchlet boundary conditions that you don't want represented
1503    in the matrix.
1504 
1505    Efficiency Alert:
1506    The routine `MatSetValuesBlocked()` may offer much better efficiency
1507    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1508 
1509     This is currently not optimized for any particular `ISType`
1510 
1511    Developer Notes:
1512     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1513                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1514 
1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1516           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1517 @*/
1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1519 {
1520   PetscInt        m, n;
1521   const PetscInt *rows, *cols;
1522 
1523   PetscFunctionBeginHot;
1524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1525   PetscCall(ISGetIndices(ism, &rows));
1526   PetscCall(ISGetIndices(isn, &cols));
1527   PetscCall(ISGetLocalSize(ism, &m));
1528   PetscCall(ISGetLocalSize(isn, &n));
1529   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1530   PetscCall(ISRestoreIndices(ism, &rows));
1531   PetscCall(ISRestoreIndices(isn, &cols));
1532   PetscFunctionReturn(PETSC_SUCCESS);
1533 }
1534 
1535 /*@
1536    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1537         values into a matrix
1538 
1539    Not Collective
1540 
1541    Input Parameters:
1542 +  mat - the matrix
1543 .  row - the (block) row to set
1544 -  v - a logically two-dimensional array of values
1545 
1546    Level: intermediate
1547 
1548    Notes:
1549    The values, `v`, are column-oriented (for the block version) and sorted
1550 
1551    All the nonzeros in the row must be provided
1552 
1553    The matrix must have previously had its column indices set, likely by having been assembled.
1554 
1555    The row must belong to this process
1556 
1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1558           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1559 @*/
1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1561 {
1562   PetscInt globalrow;
1563 
1564   PetscFunctionBegin;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   PetscValidScalarPointer(v, 3);
1568   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1569   PetscCall(MatSetValuesRow(mat, globalrow, v));
1570   PetscFunctionReturn(PETSC_SUCCESS);
1571 }
1572 
1573 /*@
1574    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1575         values into a matrix
1576 
1577    Not Collective
1578 
1579    Input Parameters:
1580 +  mat - the matrix
1581 .  row - the (block) row to set
1582 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1583 
1584    Level: advanced
1585 
1586    Notes:
1587    The values, `v`, are column-oriented for the block version.
1588 
1589    All the nonzeros in the row must be provided
1590 
1591    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1592 
1593    The row must belong to this process
1594 
1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1596           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1597 @*/
1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1599 {
1600   PetscFunctionBeginHot;
1601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1602   PetscValidType(mat, 1);
1603   MatCheckPreallocated(mat, 1);
1604   PetscValidScalarPointer(v, 3);
1605   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1606   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1607   mat->insertmode = INSERT_VALUES;
1608 
1609   if (mat->assembled) {
1610     mat->was_assembled = PETSC_TRUE;
1611     mat->assembled     = PETSC_FALSE;
1612   }
1613   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1614   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1615   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1616   PetscFunctionReturn(PETSC_SUCCESS);
1617 }
1618 
1619 /*@
1620    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1621      Using structured grid indexing
1622 
1623    Not Collective
1624 
1625    Input Parameters:
1626 +  mat - the matrix
1627 .  m - number of rows being entered
1628 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1629 .  n - number of columns being entered
1630 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1631 .  v - a logically two-dimensional array of values
1632 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1633 
1634    Level: beginner
1635 
1636    Notes:
1637    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1638 
1639    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1640    options cannot be mixed without intervening calls to the assembly
1641    routines.
1642 
1643    The grid coordinates are across the entire grid, not just the local portion
1644 
1645    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1646    as well as in C.
1647 
1648    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1649 
1650    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1651    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1652 
1653    The columns and rows in the stencil passed in MUST be contained within the
1654    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1655    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1656    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1657    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1658 
1659    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1660    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1661    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1662    `DM_BOUNDARY_PERIODIC` boundary type.
1663 
1664    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1665    a single value per point) you can skip filling those indices.
1666 
1667    Inspired by the structured grid interface to the HYPRE package
1668    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1669 
1670    Efficiency Alert:
1671    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1672    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1673 
1674    Fortran Note:
1675    `idxm` and `idxn` should be declared as
1676 $     MatStencil idxm(4,m),idxn(4,n)
1677    and the values inserted using
1678 .vb
1679     idxm(MatStencil_i,1) = i
1680     idxm(MatStencil_j,1) = j
1681     idxm(MatStencil_k,1) = k
1682     idxm(MatStencil_c,1) = c
1683     etc
1684 .ve
1685 
1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1687           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1688 @*/
1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1690 {
1691   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1692   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1693   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1694 
1695   PetscFunctionBegin;
1696   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1698   PetscValidType(mat, 1);
1699   PetscValidPointer(idxm, 3);
1700   PetscValidPointer(idxn, 5);
1701 
1702   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1703     jdxm = buf;
1704     jdxn = buf + m;
1705   } else {
1706     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1707     jdxm = bufm;
1708     jdxn = bufn;
1709   }
1710   for (i = 0; i < m; i++) {
1711     for (j = 0; j < 3 - sdim; j++) dxm++;
1712     tmp = *dxm++ - starts[0];
1713     for (j = 0; j < dim - 1; j++) {
1714       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1715       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1716     }
1717     if (mat->stencil.noc) dxm++;
1718     jdxm[i] = tmp;
1719   }
1720   for (i = 0; i < n; i++) {
1721     for (j = 0; j < 3 - sdim; j++) dxn++;
1722     tmp = *dxn++ - starts[0];
1723     for (j = 0; j < dim - 1; j++) {
1724       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1725       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1726     }
1727     if (mat->stencil.noc) dxn++;
1728     jdxn[i] = tmp;
1729   }
1730   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1731   PetscCall(PetscFree2(bufm, bufn));
1732   PetscFunctionReturn(PETSC_SUCCESS);
1733 }
1734 
1735 /*@
1736    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1737      Using structured grid indexing
1738 
1739    Not Collective
1740 
1741    Input Parameters:
1742 +  mat - the matrix
1743 .  m - number of rows being entered
1744 .  idxm - grid coordinates for matrix rows being entered
1745 .  n - number of columns being entered
1746 .  idxn - grid coordinates for matrix columns being entered
1747 .  v - a logically two-dimensional array of values
1748 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1749 
1750    Level: beginner
1751 
1752    Notes:
1753    By default the values, `v`, are row-oriented and unsorted.
1754    See `MatSetOption()` for other options.
1755 
1756    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1757    options cannot be mixed without intervening calls to the assembly
1758    routines.
1759 
1760    The grid coordinates are across the entire grid, not just the local portion
1761 
1762    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1763    as well as in C.
1764 
1765    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1766 
1767    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1768    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1769 
1770    The columns and rows in the stencil passed in MUST be contained within the
1771    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1772    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1773    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1774    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1775 
1776    Negative indices may be passed in idxm and idxn, these rows and columns are
1777    simply ignored. This allows easily inserting element stiffness matrices
1778    with homogeneous Dirchlet boundary conditions that you don't want represented
1779    in the matrix.
1780 
1781    Inspired by the structured grid interface to the HYPRE package
1782    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1783 
1784    Fortran Note:
1785    `idxm` and `idxn` should be declared as
1786 $     MatStencil idxm(4,m),idxn(4,n)
1787    and the values inserted using
1788 .vb
1789     idxm(MatStencil_i,1) = i
1790     idxm(MatStencil_j,1) = j
1791     idxm(MatStencil_k,1) = k
1792    etc
1793 .ve
1794 
1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1796           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1797           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1798 @*/
1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscValidPointer(idxm, 3);
1810   PetscValidPointer(idxn, 5);
1811   PetscValidScalarPointer(v, 6);
1812 
1813   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1814     jdxm = buf;
1815     jdxn = buf + m;
1816   } else {
1817     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1818     jdxm = bufm;
1819     jdxn = bufn;
1820   }
1821   for (i = 0; i < m; i++) {
1822     for (j = 0; j < 3 - sdim; j++) dxm++;
1823     tmp = *dxm++ - starts[0];
1824     for (j = 0; j < sdim - 1; j++) {
1825       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1826       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1827     }
1828     dxm++;
1829     jdxm[i] = tmp;
1830   }
1831   for (i = 0; i < n; i++) {
1832     for (j = 0; j < 3 - sdim; j++) dxn++;
1833     tmp = *dxn++ - starts[0];
1834     for (j = 0; j < sdim - 1; j++) {
1835       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1836       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1837     }
1838     dxn++;
1839     jdxn[i] = tmp;
1840   }
1841   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1842   PetscCall(PetscFree2(bufm, bufn));
1843   PetscFunctionReturn(PETSC_SUCCESS);
1844 }
1845 
1846 /*@
1847    MatSetStencil - Sets the grid information for setting values into a matrix via
1848         `MatSetValuesStencil()`
1849 
1850    Not Collective
1851 
1852    Input Parameters:
1853 +  mat - the matrix
1854 .  dim - dimension of the grid 1, 2, or 3
1855 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1856 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1857 -  dof - number of degrees of freedom per node
1858 
1859    Level: beginner
1860 
1861    Notes:
1862    Inspired by the structured grid interface to the HYPRE package
1863    (www.llnl.gov/CASC/hyper)
1864 
1865    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1866    user.
1867 
1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1869           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1870 @*/
1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1872 {
1873   PetscFunctionBegin;
1874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1875   PetscValidIntPointer(dims, 3);
1876   PetscValidIntPointer(starts, 4);
1877 
1878   mat->stencil.dim = dim + (dof > 1);
1879   for (PetscInt i = 0; i < dim; i++) {
1880     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1881     mat->stencil.starts[i] = starts[dim - i - 1];
1882   }
1883   mat->stencil.dims[dim]   = dof;
1884   mat->stencil.starts[dim] = 0;
1885   mat->stencil.noc         = (PetscBool)(dof == 1);
1886   PetscFunctionReturn(PETSC_SUCCESS);
1887 }
1888 
1889 /*@C
1890    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1891 
1892    Not Collective
1893 
1894    Input Parameters:
1895 +  mat - the matrix
1896 .  v - a logically two-dimensional array of values
1897 .  m  - the number of block rows
1898 .  idxm - the global block indices
1899 .  n - the number of block columns
1900 .  idxn - the global block indices
1901 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1902 
1903    Level: intermediate
1904 
1905    Notes:
1906    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1907    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1908 
1909    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1910    NOT the total number of rows/columns; for example, if the block size is 2 and
1911    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1912    The values in idxm would be 1 2; that is the first index for each block divided by
1913    the block size.
1914 
1915    You must call `MatSetBlockSize()` when constructing this matrix (before
1916    preallocating it).
1917 
1918    By default the values, `v`, are row-oriented, so the layout of
1919    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1920 
1921    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1922    options cannot be mixed without intervening calls to the assembly
1923    routines.
1924 
1925    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1926    as well as in C.
1927 
1928    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1929    simply ignored. This allows easily inserting element stiffness matrices
1930    with homogeneous Dirchlet boundary conditions that you don't want represented
1931    in the matrix.
1932 
1933    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1934    internal searching must be done to determine where to place the
1935    data in the matrix storage space.  By instead inserting blocks of
1936    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1937    reduced.
1938 
1939    Example:
1940 .vb
1941    Suppose m=n=2 and block size(bs) = 2 The array is
1942 
1943    1  2  | 3  4
1944    5  6  | 7  8
1945    - - - | - - -
1946    9  10 | 11 12
1947    13 14 | 15 16
1948 
1949    v[] should be passed in like
1950    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1951 
1952   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1953    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1954 .ve
1955 
1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1957 @*/
1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1959 {
1960   PetscFunctionBeginHot;
1961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1962   PetscValidType(mat, 1);
1963   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1964   PetscValidIntPointer(idxm, 3);
1965   PetscValidIntPointer(idxn, 5);
1966   MatCheckPreallocated(mat, 1);
1967   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1968   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1969   if (PetscDefined(USE_DEBUG)) {
1970     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1971     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1972   }
1973   if (PetscDefined(USE_DEBUG)) {
1974     PetscInt rbs, cbs, M, N, i;
1975     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1976     PetscCall(MatGetSize(mat, &M, &N));
1977     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1978     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1979   }
1980   if (mat->assembled) {
1981     mat->was_assembled = PETSC_TRUE;
1982     mat->assembled     = PETSC_FALSE;
1983   }
1984   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1985   if (mat->ops->setvaluesblocked) {
1986     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1987   } else {
1988     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1989     PetscInt i, j, bs, cbs;
1990 
1991     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1992     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1993       iidxm = buf;
1994       iidxn = buf + m * bs;
1995     } else {
1996       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1997       iidxm = bufr;
1998       iidxn = bufc;
1999     }
2000     for (i = 0; i < m; i++) {
2001       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2002     }
2003     if (m != n || bs != cbs || idxm != idxn) {
2004       for (i = 0; i < n; i++) {
2005         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2006       }
2007     } else iidxn = iidxm;
2008     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2009     PetscCall(PetscFree2(bufr, bufc));
2010   }
2011   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2012   PetscFunctionReturn(PETSC_SUCCESS);
2013 }
2014 
2015 /*@C
2016    MatGetValues - Gets a block of local values from a matrix.
2017 
2018    Not Collective; can only return values that are owned by the give process
2019 
2020    Input Parameters:
2021 +  mat - the matrix
2022 .  v - a logically two-dimensional array for storing the values
2023 .  m  - the number of rows
2024 .  idxm - the  global indices of the rows
2025 .  n - the number of columns
2026 -  idxn - the global indices of the columns
2027 
2028    Level: advanced
2029 
2030    Notes:
2031      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2032      The values, `v`, are then returned in a row-oriented format,
2033      analogous to that used by default in `MatSetValues()`.
2034 
2035      `MatGetValues()` uses 0-based row and column numbers in
2036      Fortran as well as in C.
2037 
2038      `MatGetValues()` requires that the matrix has been assembled
2039      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2040      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2041      without intermediate matrix assembly.
2042 
2043      Negative row or column indices will be ignored and those locations in `v` will be
2044      left unchanged.
2045 
2046      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2047      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2048      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2049 
2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2051 @*/
2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2053 {
2054   PetscFunctionBegin;
2055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2056   PetscValidType(mat, 1);
2057   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2058   PetscValidIntPointer(idxm, 3);
2059   PetscValidIntPointer(idxn, 5);
2060   PetscValidScalarPointer(v, 6);
2061   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2063   MatCheckPreallocated(mat, 1);
2064 
2065   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2066   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2067   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2068   PetscFunctionReturn(PETSC_SUCCESS);
2069 }
2070 
2071 /*@C
2072    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2073      defined previously by `MatSetLocalToGlobalMapping()`
2074 
2075    Not Collective
2076 
2077    Input Parameters:
2078 +  mat - the matrix
2079 .  nrow - number of rows
2080 .  irow - the row local indices
2081 .  ncol - number of columns
2082 -  icol - the column local indices
2083 
2084    Output Parameter:
2085 .  y -  a logically two-dimensional array of values
2086 
2087    Level: advanced
2088 
2089    Notes:
2090      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2091 
2092      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2093      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2094      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2095      with `MatSetLocalToGlobalMapping()`.
2096 
2097    Developer Note:
2098       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2099       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2100 
2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2102           `MatSetValuesLocal()`, `MatGetValues()`
2103 @*/
2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2105 {
2106   PetscFunctionBeginHot;
2107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2108   PetscValidType(mat, 1);
2109   MatCheckPreallocated(mat, 1);
2110   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2111   PetscValidIntPointer(irow, 3);
2112   PetscValidIntPointer(icol, 5);
2113   if (PetscDefined(USE_DEBUG)) {
2114     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2116   }
2117   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2118   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2119   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2120   else {
2121     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2122     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2123       irowm = buf;
2124       icolm = buf + nrow;
2125     } else {
2126       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2127       irowm = bufr;
2128       icolm = bufc;
2129     }
2130     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2131     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2133     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2134     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2135     PetscCall(PetscFree2(bufr, bufc));
2136   }
2137   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2138   PetscFunctionReturn(PETSC_SUCCESS);
2139 }
2140 
2141 /*@
2142   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2143   the same size. Currently, this can only be called once and creates the given matrix.
2144 
2145   Not Collective
2146 
2147   Input Parameters:
2148 + mat - the matrix
2149 . nb - the number of blocks
2150 . bs - the number of rows (and columns) in each block
2151 . rows - a concatenation of the rows for each block
2152 - v - a concatenation of logically two-dimensional arrays of values
2153 
2154   Level: advanced
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2162           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2163 @*/
2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2165 {
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2168   PetscValidType(mat, 1);
2169   PetscValidIntPointer(rows, 4);
2170   PetscValidScalarPointer(v, 5);
2171   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2172 
2173   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2174   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2175   else {
2176     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2177   }
2178   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2179   PetscFunctionReturn(PETSC_SUCCESS);
2180 }
2181 
2182 /*@
2183    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2184    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2185    using a local (per-processor) numbering.
2186 
2187    Not Collective
2188 
2189    Input Parameters:
2190 +  x - the matrix
2191 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2192 -  cmapping - column mapping
2193 
2194    Level: intermediate
2195 
2196    Note:
2197    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2198 
2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2200 @*/
2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2202 {
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2205   PetscValidType(x, 1);
2206   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2207   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2208   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2209   else {
2210     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2212   }
2213   PetscFunctionReturn(PETSC_SUCCESS);
2214 }
2215 
2216 /*@
2217    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2218 
2219    Not Collective
2220 
2221    Input Parameter:
2222 .  A - the matrix
2223 
2224    Output Parameters:
2225 + rmapping - row mapping
2226 - cmapping - column mapping
2227 
2228    Level: advanced
2229 
2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2236   PetscValidType(A, 1);
2237   if (rmapping) {
2238     PetscValidPointer(rmapping, 2);
2239     *rmapping = A->rmap->mapping;
2240   }
2241   if (cmapping) {
2242     PetscValidPointer(cmapping, 3);
2243     *cmapping = A->cmap->mapping;
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2250 
2251    Logically Collective
2252 
2253    Input Parameters:
2254 +  A - the matrix
2255 . rmap - row layout
2256 - cmap - column layout
2257 
2258    Level: advanced
2259 
2260    Note:
2261    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2262 
2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2264 @*/
2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2269   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2270   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2271   PetscFunctionReturn(PETSC_SUCCESS);
2272 }
2273 
2274 /*@
2275    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2276 
2277    Not Collective
2278 
2279    Input Parameter:
2280 .  A - the matrix
2281 
2282    Output Parameters:
2283 + rmap - row layout
2284 - cmap - column layout
2285 
2286    Level: advanced
2287 
2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2289 @*/
2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2291 {
2292   PetscFunctionBegin;
2293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2294   PetscValidType(A, 1);
2295   if (rmap) {
2296     PetscValidPointer(rmap, 2);
2297     *rmap = A->rmap;
2298   }
2299   if (cmap) {
2300     PetscValidPointer(cmap, 3);
2301     *cmap = A->cmap;
2302   }
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@C
2307    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2308    using a local numbering of the nodes.
2309 
2310    Not Collective
2311 
2312    Input Parameters:
2313 +  mat - the matrix
2314 .  nrow - number of rows
2315 .  irow - the row local indices
2316 .  ncol - number of columns
2317 .  icol - the column local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Level: intermediate
2322 
2323    Notes:
2324    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2325       `MatSetUp()` before using this routine
2326 
2327    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2328 
2329    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2330    options cannot be mixed without intervening calls to the assembly
2331    routines.
2332 
2333    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2334    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow - number of rows
2402 .  irow - the row local indices
2403 .  ncol - number of columns
2404 .  icol - the column local indices
2405 .  y -  a logically two-dimensional array of values
2406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2407 
2408    Level: intermediate
2409 
2410    Notes:
2411    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2412       `MatSetUp()` before using this routine
2413 
2414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2415       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2416 
2417    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2418    options cannot be mixed without intervening calls to the assembly
2419    routines.
2420 
2421    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2422    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2423 
2424    Developer Note:
2425     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2426                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2427 
2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2429           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2430 @*/
2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2432 {
2433   PetscFunctionBeginHot;
2434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2435   PetscValidType(mat, 1);
2436   MatCheckPreallocated(mat, 1);
2437   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2438   PetscValidIntPointer(irow, 3);
2439   PetscValidIntPointer(icol, 5);
2440   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2441   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2442   if (PetscDefined(USE_DEBUG)) {
2443     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2444     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2445   }
2446 
2447   if (mat->assembled) {
2448     mat->was_assembled = PETSC_TRUE;
2449     mat->assembled     = PETSC_FALSE;
2450   }
2451   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2452     PetscInt irbs, rbs;
2453     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2454     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2455     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2456   }
2457   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2458     PetscInt icbs, cbs;
2459     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2460     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2461     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2462   }
2463   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2464   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2465   else {
2466     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2467     const PetscInt *irowm, *icolm;
2468 
2469     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2470       bufr  = buf;
2471       bufc  = buf + nrow;
2472       irowm = bufr;
2473       icolm = bufc;
2474     } else {
2475       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2476       irowm = bufr;
2477       icolm = bufc;
2478     }
2479     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2480     else irowm = irow;
2481     if (mat->cmap->mapping) {
2482       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2483         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2484       } else icolm = irowm;
2485     } else icolm = icol;
2486     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2487     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2488   }
2489   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2490   PetscFunctionReturn(PETSC_SUCCESS);
2491 }
2492 
2493 /*@
2494    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2495 
2496    Collective
2497 
2498    Input Parameters:
2499 +  mat - the matrix
2500 -  x   - the vector to be multiplied
2501 
2502    Output Parameter:
2503 .  y - the result
2504 
2505    Level: developer
2506 
2507    Note:
2508    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2509    call `MatMultDiagonalBlock`(A,y,y).
2510 
2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2512 @*/
2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2514 {
2515   PetscFunctionBegin;
2516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2517   PetscValidType(mat, 1);
2518   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2519   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2520 
2521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2523   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2524   MatCheckPreallocated(mat, 1);
2525 
2526   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2527   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2528   PetscFunctionReturn(PETSC_SUCCESS);
2529 }
2530 
2531 /*@
2532    MatMult - Computes the matrix-vector product, y = Ax.
2533 
2534    Neighbor-wise Collective
2535 
2536    Input Parameters:
2537 +  mat - the matrix
2538 -  x   - the vector to be multiplied
2539 
2540    Output Parameter:
2541 .  y - the result
2542 
2543    Level: beginner
2544 
2545    Note:
2546    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2547    call `MatMult`(A,y,y).
2548 
2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2550 @*/
2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2552 {
2553   PetscFunctionBegin;
2554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2555   PetscValidType(mat, 1);
2556   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2557   VecCheckAssembled(x);
2558   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2561   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2562   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2563   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2564   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2565   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2566   PetscCall(VecSetErrorIfLocked(y, 3));
2567   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2568   MatCheckPreallocated(mat, 1);
2569 
2570   PetscCall(VecLockReadPush(x));
2571   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2572   PetscUseTypeMethod(mat, mult, x, y);
2573   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2574   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2575   PetscCall(VecLockReadPop(x));
2576   PetscFunctionReturn(PETSC_SUCCESS);
2577 }
2578 
2579 /*@
2580    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2581 
2582    Neighbor-wise Collective
2583 
2584    Input Parameters:
2585 +  mat - the matrix
2586 -  x   - the vector to be multiplied
2587 
2588    Output Parameter:
2589 .  y - the result
2590 
2591    Level: beginner
2592 
2593    Notes:
2594    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2595    call `MatMultTranspose`(A,y,y).
2596 
2597    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2598    use `MatMultHermitianTranspose()`
2599 
2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2601 @*/
2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2603 {
2604   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2605 
2606   PetscFunctionBegin;
2607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2608   PetscValidType(mat, 1);
2609   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2610   VecCheckAssembled(x);
2611   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2612 
2613   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2614   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2615   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2616   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2617   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2618   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2619   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2620   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2621   MatCheckPreallocated(mat, 1);
2622 
2623   if (!mat->ops->multtranspose) {
2624     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2625     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2626   } else op = mat->ops->multtranspose;
2627   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2628   PetscCall(VecLockReadPush(x));
2629   PetscCall((*op)(mat, x, y));
2630   PetscCall(VecLockReadPop(x));
2631   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2632   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2633   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2634   PetscFunctionReturn(PETSC_SUCCESS);
2635 }
2636 
2637 /*@
2638    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2639 
2640    Neighbor-wise Collective
2641 
2642    Input Parameters:
2643 +  mat - the matrix
2644 -  x   - the vector to be multilplied
2645 
2646    Output Parameter:
2647 .  y - the result
2648 
2649    Level: beginner
2650 
2651    Notes:
2652    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2653    call `MatMultHermitianTranspose`(A,y,y).
2654 
2655    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2656 
2657    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2658 
2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2660 @*/
2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2662 {
2663   PetscFunctionBegin;
2664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2665   PetscValidType(mat, 1);
2666   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2667   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2668 
2669   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2670   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2671   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2672   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2673   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2674   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2675   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2676   MatCheckPreallocated(mat, 1);
2677 
2678   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2679 #if defined(PETSC_USE_COMPLEX)
2680   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2681     PetscCall(VecLockReadPush(x));
2682     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2683     else PetscUseTypeMethod(mat, mult, x, y);
2684     PetscCall(VecLockReadPop(x));
2685   } else {
2686     Vec w;
2687     PetscCall(VecDuplicate(x, &w));
2688     PetscCall(VecCopy(x, w));
2689     PetscCall(VecConjugate(w));
2690     PetscCall(MatMultTranspose(mat, w, y));
2691     PetscCall(VecDestroy(&w));
2692     PetscCall(VecConjugate(y));
2693   }
2694   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2695 #else
2696   PetscCall(MatMultTranspose(mat, x, y));
2697 #endif
2698   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2699   PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701 
2702 /*@
2703     MatMultAdd -  Computes v3 = v2 + A * v1.
2704 
2705     Neighbor-wise Collective
2706 
2707     Input Parameters:
2708 +   mat - the matrix
2709 .   v1 - the vector to be multiplied by `mat`
2710 -   v2 - the vector to be added to the result
2711 
2712     Output Parameter:
2713 .   v3 - the result
2714 
2715     Level: beginner
2716 
2717     Note:
2718     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2719     call `MatMultAdd`(A,v1,v2,v1).
2720 
2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2722 @*/
2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2724 {
2725   PetscFunctionBegin;
2726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2727   PetscValidType(mat, 1);
2728   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2729   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2730   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2731 
2732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2734   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2735   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2736      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2737   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2738   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2739   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2740   MatCheckPreallocated(mat, 1);
2741 
2742   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2743   PetscCall(VecLockReadPush(v1));
2744   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2745   PetscCall(VecLockReadPop(v1));
2746   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2747   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2748   PetscFunctionReturn(PETSC_SUCCESS);
2749 }
2750 
2751 /*@
2752    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2753 
2754    Neighbor-wise Collective
2755 
2756    Input Parameters:
2757 +  mat - the matrix
2758 .  v1 - the vector to be multiplied by the transpose of the matrix
2759 -  v2 - the vector to be added to the result
2760 
2761    Output Parameter:
2762 .  v3 - the result
2763 
2764    Level: beginner
2765 
2766    Note:
2767    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2768    call `MatMultTransposeAdd`(A,v1,v2,v1).
2769 
2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2771 @*/
2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2773 {
2774   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2775 
2776   PetscFunctionBegin;
2777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2778   PetscValidType(mat, 1);
2779   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2780   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2781   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2782 
2783   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2784   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2785   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2786   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2787   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2788   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2789   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2790   MatCheckPreallocated(mat, 1);
2791 
2792   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2793   PetscCall(VecLockReadPush(v1));
2794   PetscCall((*op)(mat, v1, v2, v3));
2795   PetscCall(VecLockReadPop(v1));
2796   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2797   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2798   PetscFunctionReturn(PETSC_SUCCESS);
2799 }
2800 
2801 /*@
2802    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2803 
2804    Neighbor-wise Collective
2805 
2806    Input Parameters:
2807 +  mat - the matrix
2808 .  v1 - the vector to be multiplied by the Hermitian transpose
2809 -  v2 - the vector to be added to the result
2810 
2811    Output Parameter:
2812 .  v3 - the result
2813 
2814    Level: beginner
2815 
2816    Note:
2817    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2818    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2819 
2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2821 @*/
2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2823 {
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2826   PetscValidType(mat, 1);
2827   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2828   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2829   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2830 
2831   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2832   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2833   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2834   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2835   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2836   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2837   MatCheckPreallocated(mat, 1);
2838 
2839   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2840   PetscCall(VecLockReadPush(v1));
2841   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2842   else {
2843     Vec w, z;
2844     PetscCall(VecDuplicate(v1, &w));
2845     PetscCall(VecCopy(v1, w));
2846     PetscCall(VecConjugate(w));
2847     PetscCall(VecDuplicate(v3, &z));
2848     PetscCall(MatMultTranspose(mat, w, z));
2849     PetscCall(VecDestroy(&w));
2850     PetscCall(VecConjugate(z));
2851     if (v2 != v3) {
2852       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2853     } else {
2854       PetscCall(VecAXPY(v3, 1.0, z));
2855     }
2856     PetscCall(VecDestroy(&z));
2857   }
2858   PetscCall(VecLockReadPop(v1));
2859   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2860   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2861   PetscFunctionReturn(PETSC_SUCCESS);
2862 }
2863 
2864 /*@C
2865    MatGetFactorType - gets the type of factorization it is
2866 
2867    Not Collective
2868 
2869    Input Parameter:
2870 .  mat - the matrix
2871 
2872    Output Parameter:
2873 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2874 
2875    Level: intermediate
2876 
2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2878           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2879 @*/
2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2881 {
2882   PetscFunctionBegin;
2883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2884   PetscValidType(mat, 1);
2885   PetscValidPointer(t, 2);
2886   *t = mat->factortype;
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891    MatSetFactorType - sets the type of factorization it is
2892 
2893    Logically Collective
2894 
2895    Input Parameters:
2896 +  mat - the matrix
2897 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2898 
2899    Level: intermediate
2900 
2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   mat->factortype = t;
2910   PetscFunctionReturn(PETSC_SUCCESS);
2911 }
2912 
2913 /*@C
2914    MatGetInfo - Returns information about matrix storage (number of
2915    nonzeros, memory, etc.).
2916 
2917    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2918 
2919    Input Parameters:
2920 +  mat - the matrix
2921 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2922 
2923    Output Parameter:
2924 .  info - matrix information context
2925 
2926    Notes:
2927    The `MatInfo` context contains a variety of matrix data, including
2928    number of nonzeros allocated and used, number of mallocs during
2929    matrix assembly, etc.  Additional information for factored matrices
2930    is provided (such as the fill ratio, number of mallocs during
2931    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2932    when using the runtime options
2933 $       -info -mat_view ::ascii_info
2934 
2935    Example:
2936    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2937    data within the MatInfo context.  For example,
2938 .vb
2939       MatInfo info;
2940       Mat     A;
2941       double  mal, nz_a, nz_u;
2942 
2943       MatGetInfo(A,MAT_LOCAL,&info);
2944       mal  = info.mallocs;
2945       nz_a = info.nz_allocated;
2946 .ve
2947 
2948    Fortran users should declare info as a double precision
2949    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2950    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2951    a complete list of parameter names.
2952 .vb
2953       double  precision info(MAT_INFO_SIZE)
2954       double  precision mal, nz_a
2955       Mat     A
2956       integer ierr
2957 
2958       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2959       mal = info(MAT_INFO_MALLOCS)
2960       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2961 .ve
2962 
2963     Level: intermediate
2964 
2965     Developer Note:
2966     The Fortran interface is not autogenerated as the
2967     interface definition cannot be generated correctly [due to `MatInfo` argument]
2968 
2969 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2970 @*/
2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2972 {
2973   PetscFunctionBegin;
2974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2975   PetscValidType(mat, 1);
2976   PetscValidPointer(info, 3);
2977   MatCheckPreallocated(mat, 1);
2978   PetscUseTypeMethod(mat, getinfo, flag, info);
2979   PetscFunctionReturn(PETSC_SUCCESS);
2980 }
2981 
2982 /*
2983    This is used by external packages where it is not easy to get the info from the actual
2984    matrix factorization.
2985 */
2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2987 {
2988   PetscFunctionBegin;
2989   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2990   PetscFunctionReturn(PETSC_SUCCESS);
2991 }
2992 
2993 /*@C
2994    MatLUFactor - Performs in-place LU factorization of matrix.
2995 
2996    Collective
2997 
2998    Input Parameters:
2999 +  mat - the matrix
3000 .  row - row permutation
3001 .  col - column permutation
3002 -  info - options for factorization, includes
3003 .vb
3004           fill - expected fill as ratio of original fill.
3005           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3006                    Run with the option -info to determine an optimal value to use
3007 .ve
3008    Level: developer
3009 
3010    Notes:
3011    Most users should employ the `KSP` interface for linear solvers
3012    instead of working directly with matrix algebra routines such as this.
3013    See, e.g., `KSPCreate()`.
3014 
3015    This changes the state of the matrix to a factored matrix; it cannot be used
3016    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3017 
3018    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3019    when not using `KSP`.
3020 
3021    Developer Note:
3022    The Fortran interface is not autogenerated as the
3023    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3024 
3025 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3026           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3027 @*/
3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3029 {
3030   MatFactorInfo tinfo;
3031 
3032   PetscFunctionBegin;
3033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3034   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3035   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3036   if (info) PetscValidPointer(info, 4);
3037   PetscValidType(mat, 1);
3038   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3039   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3040   MatCheckPreallocated(mat, 1);
3041   if (!info) {
3042     PetscCall(MatFactorInfoInitialize(&tinfo));
3043     info = &tinfo;
3044   }
3045 
3046   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3047   PetscUseTypeMethod(mat, lufactor, row, col, info);
3048   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3049   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3050   PetscFunctionReturn(PETSC_SUCCESS);
3051 }
3052 
3053 /*@C
3054    MatILUFactor - Performs in-place ILU factorization of matrix.
3055 
3056    Collective
3057 
3058    Input Parameters:
3059 +  mat - the matrix
3060 .  row - row permutation
3061 .  col - column permutation
3062 -  info - structure containing
3063 .vb
3064       levels - number of levels of fill.
3065       expected fill - as ratio of original fill.
3066       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3067                 missing diagonal entries)
3068 .ve
3069 
3070    Level: developer
3071 
3072    Notes:
3073    Most users should employ the `KSP` interface for linear solvers
3074    instead of working directly with matrix algebra routines such as this.
3075    See, e.g., `KSPCreate()`.
3076 
3077    Probably really in-place only when level of fill is zero, otherwise allocates
3078    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3079    when not using `KSP`.
3080 
3081    Developer Note:
3082    The Fortran interface is not autogenerated as the
3083    interface definition cannot be generated correctly [due to MatFactorInfo]
3084 
3085 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3086 @*/
3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3088 {
3089   PetscFunctionBegin;
3090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3091   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3092   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3093   PetscValidPointer(info, 4);
3094   PetscValidType(mat, 1);
3095   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3096   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3097   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3098   MatCheckPreallocated(mat, 1);
3099 
3100   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3101   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3102   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3103   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3104   PetscFunctionReturn(PETSC_SUCCESS);
3105 }
3106 
3107 /*@C
3108    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3109    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3110 
3111    Collective
3112 
3113    Input Parameters:
3114 +  fact - the factor matrix obtained with `MatGetFactor()`
3115 .  mat - the matrix
3116 .  row - the row permutation
3117 .  col - the column permutation
3118 -  info - options for factorization, includes
3119 .vb
3120           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3121           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3122 .ve
3123 
3124    Level: developer
3125 
3126    Notes:
3127     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3128 
3129    Most users should employ the simplified `KSP` interface for linear solvers
3130    instead of working directly with matrix algebra routines such as this.
3131    See, e.g., `KSPCreate()`.
3132 
3133    Developer Note:
3134    The Fortran interface is not autogenerated as the
3135    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3136 
3137 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3138 @*/
3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3140 {
3141   MatFactorInfo tinfo;
3142 
3143   PetscFunctionBegin;
3144   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3146   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3147   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3148   if (info) PetscValidPointer(info, 5);
3149   PetscValidType(fact, 1);
3150   PetscValidType(mat, 2);
3151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3153   if (!fact->ops->lufactorsymbolic) {
3154     MatSolverType stype;
3155     PetscCall(MatFactorGetSolverType(fact, &stype));
3156     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3157   }
3158   MatCheckPreallocated(mat, 2);
3159   if (!info) {
3160     PetscCall(MatFactorInfoInitialize(&tinfo));
3161     info = &tinfo;
3162   }
3163 
3164   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3165   PetscCall((*fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3166   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3167   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3168   PetscFunctionReturn(PETSC_SUCCESS);
3169 }
3170 
3171 /*@C
3172    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3173    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3174 
3175    Collective
3176 
3177    Input Parameters:
3178 +  fact - the factor matrix obtained with `MatGetFactor()`
3179 .  mat - the matrix
3180 -  info - options for factorization
3181 
3182    Level: developer
3183 
3184    Notes:
3185    See `MatLUFactor()` for in-place factorization.  See
3186    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3187 
3188    Most users should employ the `KSP` interface for linear solvers
3189    instead of working directly with matrix algebra routines such as this.
3190    See, e.g., `KSPCreate()`.
3191 
3192     Developer Note:
3193     The Fortran interface is not autogenerated as the
3194     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3195 
3196 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3197 @*/
3198 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3199 {
3200   MatFactorInfo tinfo;
3201 
3202   PetscFunctionBegin;
3203   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3205   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3206   PetscValidType(fact, 1);
3207   PetscValidType(mat, 2);
3208   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3209   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,
3210              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3211 
3212   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3213   MatCheckPreallocated(mat, 2);
3214   if (!info) {
3215     PetscCall(MatFactorInfoInitialize(&tinfo));
3216     info = &tinfo;
3217   }
3218 
3219   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3220   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3221   PetscCall((*fact->ops->lufactornumeric)(fact, mat, info));
3222   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3223   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3224   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3225   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3226   PetscFunctionReturn(PETSC_SUCCESS);
3227 }
3228 
3229 /*@C
3230    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3231    symmetric matrix.
3232 
3233    Collective
3234 
3235    Input Parameters:
3236 +  mat - the matrix
3237 .  perm - row and column permutations
3238 -  f - expected fill as ratio of original fill
3239 
3240    Level: developer
3241 
3242    Notes:
3243    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3244    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3245 
3246    Most users should employ the `KSP` interface for linear solvers
3247    instead of working directly with matrix algebra routines such as this.
3248    See, e.g., `KSPCreate()`.
3249 
3250    Developer Note:
3251    The Fortran interface is not autogenerated as the
3252    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3253 
3254 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3255           `MatGetOrdering()`
3256 @*/
3257 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3258 {
3259   MatFactorInfo tinfo;
3260 
3261   PetscFunctionBegin;
3262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3263   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3264   if (info) PetscValidPointer(info, 3);
3265   PetscValidType(mat, 1);
3266   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3267   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3268   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3269   MatCheckPreallocated(mat, 1);
3270   if (!info) {
3271     PetscCall(MatFactorInfoInitialize(&tinfo));
3272     info = &tinfo;
3273   }
3274 
3275   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3276   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3277   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3278   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3279   PetscFunctionReturn(PETSC_SUCCESS);
3280 }
3281 
3282 /*@C
3283    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3284    of a symmetric matrix.
3285 
3286    Collective
3287 
3288    Input Parameters:
3289 +  fact - the factor matrix obtained with `MatGetFactor()`
3290 .  mat - the matrix
3291 .  perm - row and column permutations
3292 -  info - options for factorization, includes
3293 .vb
3294           fill - expected fill as ratio of original fill.
3295           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3296                    Run with the option -info to determine an optimal value to use
3297 .ve
3298 
3299    Level: developer
3300 
3301    Notes:
3302    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3303    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3304 
3305    Most users should employ the `KSP` interface for linear solvers
3306    instead of working directly with matrix algebra routines such as this.
3307    See, e.g., `KSPCreate()`.
3308 
3309    Developer Note:
3310    The Fortran interface is not autogenerated as the
3311    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3312 
3313 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3314           `MatGetOrdering()`
3315 @*/
3316 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3317 {
3318   MatFactorInfo tinfo;
3319 
3320   PetscFunctionBegin;
3321   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3322   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3323   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3324   if (info) PetscValidPointer(info, 4);
3325   PetscValidType(fact, 1);
3326   PetscValidType(mat, 2);
3327   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3328   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3329   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3330   if (!fact->ops->choleskyfactorsymbolic) {
3331     MatSolverType stype;
3332     PetscCall(MatFactorGetSolverType(fact, &stype));
3333     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3334   }
3335   MatCheckPreallocated(mat, 2);
3336   if (!info) {
3337     PetscCall(MatFactorInfoInitialize(&tinfo));
3338     info = &tinfo;
3339   }
3340 
3341   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3342   PetscCall((*fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3343   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3344   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3345   PetscFunctionReturn(PETSC_SUCCESS);
3346 }
3347 
3348 /*@C
3349    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3350    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3351    `MatCholeskyFactorSymbolic()`.
3352 
3353    Collective
3354 
3355    Input Parameters:
3356 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3357 .  mat - the initial matrix that is to be factored
3358 -  info - options for factorization
3359 
3360    Level: developer
3361 
3362    Note:
3363    Most users should employ the `KSP` interface for linear solvers
3364    instead of working directly with matrix algebra routines such as this.
3365    See, e.g., `KSPCreate()`.
3366 
3367    Developer Note:
3368    The Fortran interface is not autogenerated as the
3369    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3370 
3371 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3372 @*/
3373 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3374 {
3375   MatFactorInfo tinfo;
3376 
3377   PetscFunctionBegin;
3378   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3379   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3380   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3381   PetscValidType(fact, 1);
3382   PetscValidType(mat, 2);
3383   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3384   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3385   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,
3386              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3387   MatCheckPreallocated(mat, 2);
3388   if (!info) {
3389     PetscCall(MatFactorInfoInitialize(&tinfo));
3390     info = &tinfo;
3391   }
3392 
3393   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3394   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3395   PetscCall((*fact->ops->choleskyfactornumeric)(fact, mat, info));
3396   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3397   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3398   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3399   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3400   PetscFunctionReturn(PETSC_SUCCESS);
3401 }
3402 
3403 /*@
3404    MatQRFactor - Performs in-place QR factorization of matrix.
3405 
3406    Collective
3407 
3408    Input Parameters:
3409 +  mat - the matrix
3410 .  col - column permutation
3411 -  info - options for factorization, includes
3412 .vb
3413           fill - expected fill as ratio of original fill.
3414           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3415                    Run with the option -info to determine an optimal value to use
3416 .ve
3417 
3418    Level: developer
3419 
3420    Notes:
3421    Most users should employ the `KSP` interface for linear solvers
3422    instead of working directly with matrix algebra routines such as this.
3423    See, e.g., `KSPCreate()`.
3424 
3425    This changes the state of the matrix to a factored matrix; it cannot be used
3426    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3427 
3428    Developer Note:
3429    The Fortran interface is not autogenerated as the
3430    interface definition cannot be generated correctly [due to MatFactorInfo]
3431 
3432 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3433           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3434 @*/
3435 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3436 {
3437   PetscFunctionBegin;
3438   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3439   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3440   if (info) PetscValidPointer(info, 3);
3441   PetscValidType(mat, 1);
3442   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3443   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3444   MatCheckPreallocated(mat, 1);
3445   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3446   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3447   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3448   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3449   PetscFunctionReturn(PETSC_SUCCESS);
3450 }
3451 
3452 /*@
3453    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3454    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3455 
3456    Collective
3457 
3458    Input Parameters:
3459 +  fact - the factor matrix obtained with `MatGetFactor()`
3460 .  mat - the matrix
3461 .  col - column permutation
3462 -  info - options for factorization, includes
3463 .vb
3464           fill - expected fill as ratio of original fill.
3465           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3466                    Run with the option -info to determine an optimal value to use
3467 .ve
3468 
3469    Level: developer
3470 
3471    Note:
3472    Most users should employ the `KSP` interface for linear solvers
3473    instead of working directly with matrix algebra routines such as this.
3474    See, e.g., `KSPCreate()`.
3475 
3476    Developer Note:
3477    The Fortran interface is not autogenerated as the
3478    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3479 
3480 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3481 @*/
3482 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3483 {
3484   MatFactorInfo tinfo;
3485 
3486   PetscFunctionBegin;
3487   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3489   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3490   if (info) PetscValidPointer(info, 4);
3491   PetscValidType(fact, 1);
3492   PetscValidType(mat, 2);
3493   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3494   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3495   MatCheckPreallocated(mat, 2);
3496   if (!info) {
3497     PetscCall(MatFactorInfoInitialize(&tinfo));
3498     info = &tinfo;
3499   }
3500 
3501   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3502   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3503   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3504   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3505   PetscFunctionReturn(PETSC_SUCCESS);
3506 }
3507 
3508 /*@
3509    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3510    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3511 
3512    Collective
3513 
3514    Input Parameters:
3515 +  fact - the factor matrix obtained with `MatGetFactor()`
3516 .  mat - the matrix
3517 -  info - options for factorization
3518 
3519    Level: developer
3520 
3521    Notes:
3522    See `MatQRFactor()` for in-place factorization.
3523 
3524    Most users should employ the `KSP` interface for linear solvers
3525    instead of working directly with matrix algebra routines such as this.
3526    See, e.g., `KSPCreate()`.
3527 
3528    Developer Note:
3529    The Fortran interface is not autogenerated as the
3530    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3531 
3532 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3533 @*/
3534 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3535 {
3536   MatFactorInfo tinfo;
3537 
3538   PetscFunctionBegin;
3539   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3541   PetscValidType(fact, 1);
3542   PetscValidType(mat, 2);
3543   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3544   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,
3545              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3546 
3547   MatCheckPreallocated(mat, 2);
3548   if (!info) {
3549     PetscCall(MatFactorInfoInitialize(&tinfo));
3550     info = &tinfo;
3551   }
3552 
3553   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3554   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3555   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3556   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3557   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3558   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3559   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3560   PetscFunctionReturn(PETSC_SUCCESS);
3561 }
3562 
3563 /*@
3564    MatSolve - Solves A x = b, given a factored matrix.
3565 
3566    Neighbor-wise Collective
3567 
3568    Input Parameters:
3569 +  mat - the factored matrix
3570 -  b - the right-hand-side vector
3571 
3572    Output Parameter:
3573 .  x - the result vector
3574 
3575    Level: developer
3576 
3577    Notes:
3578    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3579    call `MatSolve`(A,x,x).
3580 
3581    Most users should employ the `KSP` interface for linear solvers
3582    instead of working directly with matrix algebra routines such as this.
3583    See, e.g., `KSPCreate()`.
3584 
3585 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3586 @*/
3587 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3588 {
3589   PetscFunctionBegin;
3590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3591   PetscValidType(mat, 1);
3592   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3593   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3594   PetscCheckSameComm(mat, 1, b, 2);
3595   PetscCheckSameComm(mat, 1, x, 3);
3596   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3597   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);
3598   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);
3599   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);
3600   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3601   MatCheckPreallocated(mat, 1);
3602 
3603   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3604   if (mat->factorerrortype) {
3605     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3606     PetscCall(VecSetInf(x));
3607   } else PetscUseTypeMethod(mat, solve, b, x);
3608   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3609   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3610   PetscFunctionReturn(PETSC_SUCCESS);
3611 }
3612 
3613 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3614 {
3615   Vec      b, x;
3616   PetscInt N, i;
3617   PetscErrorCode (*f)(Mat, Vec, Vec);
3618   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3619 
3620   PetscFunctionBegin;
3621   if (A->factorerrortype) {
3622     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3623     PetscCall(MatSetInf(X));
3624     PetscFunctionReturn(PETSC_SUCCESS);
3625   }
3626   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3627   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3628   PetscCall(MatBoundToCPU(A, &Abound));
3629   if (!Abound) {
3630     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3631     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3632   }
3633 #if defined(PETSC_HAVE_CUDA)
3634   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3635   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3636 #elif (PETSC_HAVE_HIP)
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3639 #endif
3640   PetscCall(MatGetSize(B, NULL, &N));
3641   for (i = 0; i < N; i++) {
3642     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3643     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3644     PetscCall((*f)(A, b, x));
3645     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3646     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3647   }
3648   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3649   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3650   PetscFunctionReturn(PETSC_SUCCESS);
3651 }
3652 
3653 /*@
3654    MatMatSolve - Solves A X = B, given a factored matrix.
3655 
3656    Neighbor-wise Collective
3657 
3658    Input Parameters:
3659 +  A - the factored matrix
3660 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3661 
3662    Output Parameter:
3663 .  X - the result matrix (dense matrix)
3664 
3665    Level: developer
3666 
3667    Note:
3668    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3669    otherwise, `B` and `X` cannot be the same.
3670 
3671 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3672 @*/
3673 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3674 {
3675   PetscFunctionBegin;
3676   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3677   PetscValidType(A, 1);
3678   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3679   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3680   PetscCheckSameComm(A, 1, B, 2);
3681   PetscCheckSameComm(A, 1, X, 3);
3682   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);
3683   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);
3684   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");
3685   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3686   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3687   MatCheckPreallocated(A, 1);
3688 
3689   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3690   if (!A->ops->matsolve) {
3691     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3692     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3693   } else PetscUseTypeMethod(A, matsolve, B, X);
3694   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3695   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3696   PetscFunctionReturn(PETSC_SUCCESS);
3697 }
3698 
3699 /*@
3700    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3701 
3702    Neighbor-wise Collective
3703 
3704    Input Parameters:
3705 +  A - the factored matrix
3706 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3707 
3708    Output Parameter:
3709 .  X - the result matrix (dense matrix)
3710 
3711    Level: developer
3712 
3713    Note:
3714    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3715    call `MatMatSolveTranspose`(A,X,X).
3716 
3717 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3718 @*/
3719 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3720 {
3721   PetscFunctionBegin;
3722   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3723   PetscValidType(A, 1);
3724   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3725   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3726   PetscCheckSameComm(A, 1, B, 2);
3727   PetscCheckSameComm(A, 1, X, 3);
3728   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3729   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);
3730   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);
3731   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);
3732   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");
3733   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3734   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3735   MatCheckPreallocated(A, 1);
3736 
3737   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3738   if (!A->ops->matsolvetranspose) {
3739     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3740     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3741   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3742   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3743   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3744   PetscFunctionReturn(PETSC_SUCCESS);
3745 }
3746 
3747 /*@
3748    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3749 
3750    Neighbor-wise Collective
3751 
3752    Input Parameters:
3753 +  A - the factored matrix
3754 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3755 
3756    Output Parameter:
3757 .  X - the result matrix (dense matrix)
3758 
3759    Level: developer
3760 
3761    Note:
3762    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
3763    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3764 
3765 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3766 @*/
3767 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3768 {
3769   PetscFunctionBegin;
3770   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3771   PetscValidType(A, 1);
3772   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3773   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3774   PetscCheckSameComm(A, 1, Bt, 2);
3775   PetscCheckSameComm(A, 1, X, 3);
3776 
3777   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3778   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);
3779   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);
3780   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");
3781   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3782   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3783   MatCheckPreallocated(A, 1);
3784 
3785   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3786   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3787   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3788   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3789   PetscFunctionReturn(PETSC_SUCCESS);
3790 }
3791 
3792 /*@
3793    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3794                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3795 
3796    Neighbor-wise Collective
3797 
3798    Input Parameters:
3799 +  mat - the factored matrix
3800 -  b - the right-hand-side vector
3801 
3802    Output Parameter:
3803 .  x - the result vector
3804 
3805    Level: developer
3806 
3807    Notes:
3808    `MatSolve()` should be used for most applications, as it performs
3809    a forward solve followed by a backward solve.
3810 
3811    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3812    call `MatForwardSolve`(A,x,x).
3813 
3814    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3815    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3816    `MatForwardSolve()` solves U^T*D y = b, and
3817    `MatBackwardSolve()` solves U x = y.
3818    Thus they do not provide a symmetric preconditioner.
3819 
3820 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3821 @*/
3822 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3823 {
3824   PetscFunctionBegin;
3825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3826   PetscValidType(mat, 1);
3827   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3828   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3829   PetscCheckSameComm(mat, 1, b, 2);
3830   PetscCheckSameComm(mat, 1, x, 3);
3831   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3832   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);
3833   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);
3834   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);
3835   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3836   MatCheckPreallocated(mat, 1);
3837 
3838   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3839   PetscUseTypeMethod(mat, forwardsolve, b, x);
3840   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3841   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3842   PetscFunctionReturn(PETSC_SUCCESS);
3843 }
3844 
3845 /*@
3846    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3847                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3848 
3849    Neighbor-wise Collective
3850 
3851    Input Parameters:
3852 +  mat - the factored matrix
3853 -  b - the right-hand-side vector
3854 
3855    Output Parameter:
3856 .  x - the result vector
3857 
3858    Level: developer
3859 
3860    Notes:
3861    `MatSolve()` should be used for most applications, as it performs
3862    a forward solve followed by a backward solve.
3863 
3864    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3865    call `MatBackwardSolve`(A,x,x).
3866 
3867    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3868    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3869    `MatForwardSolve()` solves U^T*D y = b, and
3870    `MatBackwardSolve()` solves U x = y.
3871    Thus they do not provide a symmetric preconditioner.
3872 
3873 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3874 @*/
3875 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3876 {
3877   PetscFunctionBegin;
3878   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3879   PetscValidType(mat, 1);
3880   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3881   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3882   PetscCheckSameComm(mat, 1, b, 2);
3883   PetscCheckSameComm(mat, 1, x, 3);
3884   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3885   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);
3886   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);
3887   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);
3888   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3889   MatCheckPreallocated(mat, 1);
3890 
3891   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3892   PetscUseTypeMethod(mat, backwardsolve, b, x);
3893   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3894   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3895   PetscFunctionReturn(PETSC_SUCCESS);
3896 }
3897 
3898 /*@
3899    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3900 
3901    Neighbor-wise Collective
3902 
3903    Input Parameters:
3904 +  mat - the factored matrix
3905 .  b - the right-hand-side vector
3906 -  y - the vector to be added to
3907 
3908    Output Parameter:
3909 .  x - the result vector
3910 
3911    Level: developer
3912 
3913    Note:
3914    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3915    call `MatSolveAdd`(A,x,y,x).
3916 
3917 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3918 @*/
3919 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3920 {
3921   PetscScalar one = 1.0;
3922   Vec         tmp;
3923 
3924   PetscFunctionBegin;
3925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3926   PetscValidType(mat, 1);
3927   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3928   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3929   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3930   PetscCheckSameComm(mat, 1, b, 2);
3931   PetscCheckSameComm(mat, 1, y, 3);
3932   PetscCheckSameComm(mat, 1, x, 4);
3933   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3934   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);
3935   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);
3936   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);
3937   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);
3938   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);
3939   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3940   MatCheckPreallocated(mat, 1);
3941 
3942   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3943   if (mat->factorerrortype) {
3944     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3945     PetscCall(VecSetInf(x));
3946   } else if (mat->ops->solveadd) {
3947     PetscUseTypeMethod(mat, solveadd, b, y, x);
3948   } else {
3949     /* do the solve then the add manually */
3950     if (x != y) {
3951       PetscCall(MatSolve(mat, b, x));
3952       PetscCall(VecAXPY(x, one, y));
3953     } else {
3954       PetscCall(VecDuplicate(x, &tmp));
3955       PetscCall(VecCopy(x, tmp));
3956       PetscCall(MatSolve(mat, b, x));
3957       PetscCall(VecAXPY(x, one, tmp));
3958       PetscCall(VecDestroy(&tmp));
3959     }
3960   }
3961   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3962   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3963   PetscFunctionReturn(PETSC_SUCCESS);
3964 }
3965 
3966 /*@
3967    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3968 
3969    Neighbor-wise Collective
3970 
3971    Input Parameters:
3972 +  mat - the factored matrix
3973 -  b - the right-hand-side vector
3974 
3975    Output Parameter:
3976 .  x - the result vector
3977 
3978    Level: developer
3979 
3980    Notes:
3981    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3982    call `MatSolveTranspose`(A,x,x).
3983 
3984    Most users should employ the `KSP` interface for linear solvers
3985    instead of working directly with matrix algebra routines such as this.
3986    See, e.g., `KSPCreate()`.
3987 
3988 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3989 @*/
3990 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3991 {
3992   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3993 
3994   PetscFunctionBegin;
3995   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3996   PetscValidType(mat, 1);
3997   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3998   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3999   PetscCheckSameComm(mat, 1, b, 2);
4000   PetscCheckSameComm(mat, 1, x, 3);
4001   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4002   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);
4003   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);
4004   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4005   MatCheckPreallocated(mat, 1);
4006   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4007   if (mat->factorerrortype) {
4008     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4009     PetscCall(VecSetInf(x));
4010   } else {
4011     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4012     PetscCall((*f)(mat, b, x));
4013   }
4014   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4015   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4016   PetscFunctionReturn(PETSC_SUCCESS);
4017 }
4018 
4019 /*@
4020    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4021                       factored matrix.
4022 
4023    Neighbor-wise Collective
4024 
4025    Input Parameters:
4026 +  mat - the factored matrix
4027 .  b - the right-hand-side vector
4028 -  y - the vector to be added to
4029 
4030    Output Parameter:
4031 .  x - the result vector
4032 
4033    Level: developer
4034 
4035    Note:
4036    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4037    call `MatSolveTransposeAdd`(A,x,y,x).
4038 
4039 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4040 @*/
4041 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4042 {
4043   PetscScalar one = 1.0;
4044   Vec         tmp;
4045   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4046 
4047   PetscFunctionBegin;
4048   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4049   PetscValidType(mat, 1);
4050   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4051   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4052   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4053   PetscCheckSameComm(mat, 1, b, 2);
4054   PetscCheckSameComm(mat, 1, y, 3);
4055   PetscCheckSameComm(mat, 1, x, 4);
4056   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4057   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);
4058   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);
4059   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);
4060   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);
4061   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4062   MatCheckPreallocated(mat, 1);
4063 
4064   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4065   if (mat->factorerrortype) {
4066     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4067     PetscCall(VecSetInf(x));
4068   } else if (f) {
4069     PetscCall((*f)(mat, b, y, x));
4070   } else {
4071     /* do the solve then the add manually */
4072     if (x != y) {
4073       PetscCall(MatSolveTranspose(mat, b, x));
4074       PetscCall(VecAXPY(x, one, y));
4075     } else {
4076       PetscCall(VecDuplicate(x, &tmp));
4077       PetscCall(VecCopy(x, tmp));
4078       PetscCall(MatSolveTranspose(mat, b, x));
4079       PetscCall(VecAXPY(x, one, tmp));
4080       PetscCall(VecDestroy(&tmp));
4081     }
4082   }
4083   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4084   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4085   PetscFunctionReturn(PETSC_SUCCESS);
4086 }
4087 
4088 /*@
4089    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4090 
4091    Neighbor-wise Collective
4092 
4093    Input Parameters:
4094 +  mat - the matrix
4095 .  b - the right hand side
4096 .  omega - the relaxation factor
4097 .  flag - flag indicating the type of SOR (see below)
4098 .  shift -  diagonal shift
4099 .  its - the number of iterations
4100 -  lits - the number of local iterations
4101 
4102    Output Parameter:
4103 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4104 
4105    SOR Flags:
4106 +     `SOR_FORWARD_SWEEP` - forward SOR
4107 .     `SOR_BACKWARD_SWEEP` - backward SOR
4108 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4109 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4110 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4111 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4112 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4113 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4114          upper/lower triangular part of matrix to
4115          vector (with omega)
4116 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4117 
4118    Level: developer
4119 
4120    Notes:
4121    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4122    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4123    on each processor.
4124 
4125    Application programmers will not generally use `MatSOR()` directly,
4126    but instead will employ the `KSP`/`PC` interface.
4127 
4128    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4129 
4130    Most users should employ the `KSP` interface for linear solvers
4131    instead of working directly with matrix algebra routines such as this.
4132    See, e.g., `KSPCreate()`.
4133 
4134    Vectors `x` and `b` CANNOT be the same
4135 
4136    The flags are implemented as bitwise inclusive or operations.
4137    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4138    to specify a zero initial guess for SSOR.
4139 
4140    Developer Note:
4141    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4142 
4143 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4144 @*/
4145 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4146 {
4147   PetscFunctionBegin;
4148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4149   PetscValidType(mat, 1);
4150   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4151   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4152   PetscCheckSameComm(mat, 1, b, 2);
4153   PetscCheckSameComm(mat, 1, x, 8);
4154   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4155   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4156   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);
4157   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);
4158   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);
4159   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4160   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4161   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4162 
4163   MatCheckPreallocated(mat, 1);
4164   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4165   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4166   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4167   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4168   PetscFunctionReturn(PETSC_SUCCESS);
4169 }
4170 
4171 /*
4172       Default matrix copy routine.
4173 */
4174 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4175 {
4176   PetscInt           i, rstart = 0, rend = 0, nz;
4177   const PetscInt    *cwork;
4178   const PetscScalar *vwork;
4179 
4180   PetscFunctionBegin;
4181   if (B->assembled) PetscCall(MatZeroEntries(B));
4182   if (str == SAME_NONZERO_PATTERN) {
4183     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4184     for (i = rstart; i < rend; i++) {
4185       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4186       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4187       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4188     }
4189   } else {
4190     PetscCall(MatAYPX(B, 0.0, A, str));
4191   }
4192   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4193   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4194   PetscFunctionReturn(PETSC_SUCCESS);
4195 }
4196 
4197 /*@
4198    MatCopy - Copies a matrix to another matrix.
4199 
4200    Collective
4201 
4202    Input Parameters:
4203 +  A - the matrix
4204 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4205 
4206    Output Parameter:
4207 .  B - where the copy is put
4208 
4209    Level: intermediate
4210 
4211    Notes:
4212    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4213 
4214    `MatCopy()` copies the matrix entries of a matrix to another existing
4215    matrix (after first zeroing the second matrix).  A related routine is
4216    `MatConvert()`, which first creates a new matrix and then copies the data.
4217 
4218 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4219 @*/
4220 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4221 {
4222   PetscInt i;
4223 
4224   PetscFunctionBegin;
4225   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4226   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4227   PetscValidType(A, 1);
4228   PetscValidType(B, 2);
4229   PetscCheckSameComm(A, 1, B, 2);
4230   MatCheckPreallocated(B, 2);
4231   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4232   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4233   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,
4234              A->cmap->N, B->cmap->N);
4235   MatCheckPreallocated(A, 1);
4236   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4237 
4238   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4239   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4240   else PetscCall(MatCopy_Basic(A, B, str));
4241 
4242   B->stencil.dim = A->stencil.dim;
4243   B->stencil.noc = A->stencil.noc;
4244   for (i = 0; i <= A->stencil.dim; i++) {
4245     B->stencil.dims[i]   = A->stencil.dims[i];
4246     B->stencil.starts[i] = A->stencil.starts[i];
4247   }
4248 
4249   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4250   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4251   PetscFunctionReturn(PETSC_SUCCESS);
4252 }
4253 
4254 /*@C
4255    MatConvert - Converts a matrix to another matrix, either of the same
4256    or different type.
4257 
4258    Collective
4259 
4260    Input Parameters:
4261 +  mat - the matrix
4262 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4263    same type as the original matrix.
4264 -  reuse - denotes if the destination matrix is to be created or reused.
4265    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
4266    `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).
4267 
4268    Output Parameter:
4269 .  M - pointer to place new matrix
4270 
4271    Level: intermediate
4272 
4273    Notes:
4274    `MatConvert()` first creates a new matrix and then copies the data from
4275    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4276    entries of one matrix to another already existing matrix context.
4277 
4278    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4279    the MPI communicator of the generated matrix is always the same as the communicator
4280    of the input matrix.
4281 
4282 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4283 @*/
4284 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4285 {
4286   PetscBool  sametype, issame, flg;
4287   PetscBool3 issymmetric, ishermitian;
4288   char       convname[256], mtype[256];
4289   Mat        B;
4290 
4291   PetscFunctionBegin;
4292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4293   PetscValidType(mat, 1);
4294   PetscValidPointer(M, 4);
4295   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4296   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4297   MatCheckPreallocated(mat, 1);
4298 
4299   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4300   if (flg) newtype = mtype;
4301 
4302   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4303   PetscCall(PetscStrcmp(newtype, "same", &issame));
4304   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4305   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");
4306 
4307   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4308     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4309     PetscFunctionReturn(PETSC_SUCCESS);
4310   }
4311 
4312   /* Cache Mat options because some converters use MatHeaderReplace  */
4313   issymmetric = mat->symmetric;
4314   ishermitian = mat->hermitian;
4315 
4316   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4317     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4318     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4319   } else {
4320     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4321     const char *prefix[3]                                 = {"seq", "mpi", ""};
4322     PetscInt    i;
4323     /*
4324        Order of precedence:
4325        0) See if newtype is a superclass of the current matrix.
4326        1) See if a specialized converter is known to the current matrix.
4327        2) See if a specialized converter is known to the desired matrix class.
4328        3) See if a good general converter is registered for the desired class
4329           (as of 6/27/03 only MATMPIADJ falls into this category).
4330        4) See if a good general converter is known for the current matrix.
4331        5) Use a really basic converter.
4332     */
4333 
4334     /* 0) See if newtype is a superclass of the current matrix.
4335           i.e mat is mpiaij and newtype is aij */
4336     for (i = 0; i < 2; i++) {
4337       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4338       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4339       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4340       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4341       if (flg) {
4342         if (reuse == MAT_INPLACE_MATRIX) {
4343           PetscCall(PetscInfo(mat, "Early return\n"));
4344           PetscFunctionReturn(PETSC_SUCCESS);
4345         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4346           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4347           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4348           PetscFunctionReturn(PETSC_SUCCESS);
4349         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4350           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4351           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4352           PetscFunctionReturn(PETSC_SUCCESS);
4353         }
4354       }
4355     }
4356     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4357     for (i = 0; i < 3; i++) {
4358       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4359       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4364       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4365       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4366       if (conv) goto foundconv;
4367     }
4368 
4369     /* 2)  See if a specialized converter is known to the desired matrix class. */
4370     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4371     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4372     PetscCall(MatSetType(B, newtype));
4373     for (i = 0; i < 3; i++) {
4374       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4381       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4382       if (conv) {
4383         PetscCall(MatDestroy(&B));
4384         goto foundconv;
4385       }
4386     }
4387 
4388     /* 3) See if a good general converter is registered for the desired class */
4389     conv = B->ops->convertfrom;
4390     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4391     PetscCall(MatDestroy(&B));
4392     if (conv) goto foundconv;
4393 
4394     /* 4) See if a good general converter is known for the current matrix */
4395     if (mat->ops->convert) conv = mat->ops->convert;
4396     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4397     if (conv) goto foundconv;
4398 
4399     /* 5) Use a really basic converter. */
4400     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4401     conv = MatConvert_Basic;
4402 
4403   foundconv:
4404     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4405     PetscCall((*conv)(mat, newtype, reuse, M));
4406     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4407       /* the block sizes must be same if the mappings are copied over */
4408       (*M)->rmap->bs = mat->rmap->bs;
4409       (*M)->cmap->bs = mat->cmap->bs;
4410       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4411       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4412       (*M)->rmap->mapping = mat->rmap->mapping;
4413       (*M)->cmap->mapping = mat->cmap->mapping;
4414     }
4415     (*M)->stencil.dim = mat->stencil.dim;
4416     (*M)->stencil.noc = mat->stencil.noc;
4417     for (i = 0; i <= mat->stencil.dim; i++) {
4418       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4419       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4420     }
4421     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4422   }
4423   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4424 
4425   /* Copy Mat options */
4426   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4427   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4428   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4429   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4430   PetscFunctionReturn(PETSC_SUCCESS);
4431 }
4432 
4433 /*@C
4434    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4435 
4436    Not Collective
4437 
4438    Input Parameter:
4439 .  mat - the matrix, must be a factored matrix
4440 
4441    Output Parameter:
4442 .   type - the string name of the package (do not free this string)
4443 
4444    Level: intermediate
4445 
4446    Fortran Note:
4447    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4448 
4449 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4450 @*/
4451 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4452 {
4453   PetscErrorCode (*conv)(Mat, MatSolverType *);
4454 
4455   PetscFunctionBegin;
4456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4457   PetscValidType(mat, 1);
4458   PetscValidPointer(type, 2);
4459   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4460   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4461   if (conv) PetscCall((*conv)(mat, type));
4462   else *type = MATSOLVERPETSC;
4463   PetscFunctionReturn(PETSC_SUCCESS);
4464 }
4465 
4466 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4467 struct _MatSolverTypeForSpecifcType {
4468   MatType mtype;
4469   /* no entry for MAT_FACTOR_NONE */
4470   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4471   MatSolverTypeForSpecifcType next;
4472 };
4473 
4474 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4475 struct _MatSolverTypeHolder {
4476   char                       *name;
4477   MatSolverTypeForSpecifcType handlers;
4478   MatSolverTypeHolder         next;
4479 };
4480 
4481 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4482 
4483 /*@C
4484    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4485 
4486    Input Parameters:
4487 +    package - name of the package, for example petsc or superlu
4488 .    mtype - the matrix type that works with this package
4489 .    ftype - the type of factorization supported by the package
4490 -    createfactor - routine that will create the factored matrix ready to be used
4491 
4492     Level: developer
4493 
4494 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4495 @*/
4496 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4497 {
4498   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4499   PetscBool                   flg;
4500   MatSolverTypeForSpecifcType inext, iprev = NULL;
4501 
4502   PetscFunctionBegin;
4503   PetscCall(MatInitializePackage());
4504   if (!next) {
4505     PetscCall(PetscNew(&MatSolverTypeHolders));
4506     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4507     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4508     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4509     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4510     PetscFunctionReturn(PETSC_SUCCESS);
4511   }
4512   while (next) {
4513     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4514     if (flg) {
4515       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4516       inext = next->handlers;
4517       while (inext) {
4518         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4519         if (flg) {
4520           inext->createfactor[(int)ftype - 1] = createfactor;
4521           PetscFunctionReturn(PETSC_SUCCESS);
4522         }
4523         iprev = inext;
4524         inext = inext->next;
4525       }
4526       PetscCall(PetscNew(&iprev->next));
4527       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4528       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4529       PetscFunctionReturn(PETSC_SUCCESS);
4530     }
4531     prev = next;
4532     next = next->next;
4533   }
4534   PetscCall(PetscNew(&prev->next));
4535   PetscCall(PetscStrallocpy(package, &prev->next->name));
4536   PetscCall(PetscNew(&prev->next->handlers));
4537   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4538   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4539   PetscFunctionReturn(PETSC_SUCCESS);
4540 }
4541 
4542 /*@C
4543    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4544 
4545    Input Parameters:
4546 +    type - name of the package, for example petsc or superlu
4547 .    ftype - the type of factorization supported by the type
4548 -    mtype - the matrix type that works with this type
4549 
4550    Output Parameters:
4551 +   foundtype - `PETSC_TRUE` if the type was registered
4552 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4553 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4554 
4555     Level: developer
4556 
4557 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4558 @*/
4559 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4560 {
4561   MatSolverTypeHolder         next = MatSolverTypeHolders;
4562   PetscBool                   flg;
4563   MatSolverTypeForSpecifcType inext;
4564 
4565   PetscFunctionBegin;
4566   if (foundtype) *foundtype = PETSC_FALSE;
4567   if (foundmtype) *foundmtype = PETSC_FALSE;
4568   if (createfactor) *createfactor = NULL;
4569 
4570   if (type) {
4571     while (next) {
4572       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4573       if (flg) {
4574         if (foundtype) *foundtype = PETSC_TRUE;
4575         inext = next->handlers;
4576         while (inext) {
4577           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4578           if (flg) {
4579             if (foundmtype) *foundmtype = PETSC_TRUE;
4580             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4581             PetscFunctionReturn(PETSC_SUCCESS);
4582           }
4583           inext = inext->next;
4584         }
4585       }
4586       next = next->next;
4587     }
4588   } else {
4589     while (next) {
4590       inext = next->handlers;
4591       while (inext) {
4592         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4593         if (flg && inext->createfactor[(int)ftype - 1]) {
4594           if (foundtype) *foundtype = PETSC_TRUE;
4595           if (foundmtype) *foundmtype = PETSC_TRUE;
4596           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4597           PetscFunctionReturn(PETSC_SUCCESS);
4598         }
4599         inext = inext->next;
4600       }
4601       next = next->next;
4602     }
4603     /* try with base classes inext->mtype */
4604     next = MatSolverTypeHolders;
4605     while (next) {
4606       inext = next->handlers;
4607       while (inext) {
4608         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4609         if (flg && inext->createfactor[(int)ftype - 1]) {
4610           if (foundtype) *foundtype = PETSC_TRUE;
4611           if (foundmtype) *foundmtype = PETSC_TRUE;
4612           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4613           PetscFunctionReturn(PETSC_SUCCESS);
4614         }
4615         inext = inext->next;
4616       }
4617       next = next->next;
4618     }
4619   }
4620   PetscFunctionReturn(PETSC_SUCCESS);
4621 }
4622 
4623 PetscErrorCode MatSolverTypeDestroy(void)
4624 {
4625   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4626   MatSolverTypeForSpecifcType inext, iprev;
4627 
4628   PetscFunctionBegin;
4629   while (next) {
4630     PetscCall(PetscFree(next->name));
4631     inext = next->handlers;
4632     while (inext) {
4633       PetscCall(PetscFree(inext->mtype));
4634       iprev = inext;
4635       inext = inext->next;
4636       PetscCall(PetscFree(iprev));
4637     }
4638     prev = next;
4639     next = next->next;
4640     PetscCall(PetscFree(prev));
4641   }
4642   MatSolverTypeHolders = NULL;
4643   PetscFunctionReturn(PETSC_SUCCESS);
4644 }
4645 
4646 /*@C
4647    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4648 
4649    Logically Collective
4650 
4651    Input Parameter:
4652 .  mat - the matrix
4653 
4654    Output Parameter:
4655 .  flg - `PETSC_TRUE` if uses the ordering
4656 
4657    Level: developer
4658 
4659    Note:
4660    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4661    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4662 
4663 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4664 @*/
4665 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4666 {
4667   PetscFunctionBegin;
4668   *flg = mat->canuseordering;
4669   PetscFunctionReturn(PETSC_SUCCESS);
4670 }
4671 
4672 /*@C
4673    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4674 
4675    Logically Collective
4676 
4677    Input Parameters:
4678 +  mat - the matrix obtained with `MatGetFactor()`
4679 -  ftype - the factorization type to be used
4680 
4681    Output Parameter:
4682 .  otype - the preferred ordering type
4683 
4684    Level: developer
4685 
4686 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4687 @*/
4688 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4689 {
4690   PetscFunctionBegin;
4691   *otype = mat->preferredordering[ftype];
4692   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4693   PetscFunctionReturn(PETSC_SUCCESS);
4694 }
4695 
4696 /*@C
4697    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4698 
4699    Collective
4700 
4701    Input Parameters:
4702 +  mat - the matrix
4703 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4704 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4705 
4706    Output Parameter:
4707 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4708 
4709    Options Database Key:
4710 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4711                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4712 
4713    Level: intermediate
4714 
4715    Notes:
4716      Users usually access the factorization solvers via `KSP`
4717 
4718       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4719      such as pastix, superlu, mumps etc.
4720 
4721       PETSc must have been ./configure to use the external solver, using the option --download-package
4722 
4723       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4724       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4725       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4726 
4727    Developer Note:
4728       This should actually be called `MatCreateFactor()` since it creates a new factor object
4729 
4730 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4731           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4732 @*/
4733 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4734 {
4735   PetscBool foundtype, foundmtype;
4736   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4737 
4738   PetscFunctionBegin;
4739   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4740   PetscValidType(mat, 1);
4741 
4742   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4743   MatCheckPreallocated(mat, 1);
4744 
4745   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4746   if (!foundtype) {
4747     if (type) {
4748       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],
4749               ((PetscObject)mat)->type_name, type);
4750     } else {
4751       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);
4752     }
4753   }
4754   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4755   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);
4756 
4757   PetscCall((*conv)(mat, ftype, f));
4758   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4759   PetscFunctionReturn(PETSC_SUCCESS);
4760 }
4761 
4762 /*@C
4763    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4764 
4765    Not Collective
4766 
4767    Input Parameters:
4768 +  mat - the matrix
4769 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4770 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4771 
4772    Output Parameter:
4773 .    flg - PETSC_TRUE if the factorization is available
4774 
4775    Level: intermediate
4776 
4777    Notes:
4778       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4779      such as pastix, superlu, mumps etc.
4780 
4781       PETSc must have been ./configure to use the external solver, using the option --download-package
4782 
4783    Developer Note:
4784       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4785 
4786 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4787           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4788 @*/
4789 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4790 {
4791   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4792 
4793   PetscFunctionBegin;
4794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4795   PetscValidType(mat, 1);
4796   PetscValidBoolPointer(flg, 4);
4797 
4798   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4799   MatCheckPreallocated(mat, 1);
4800 
4801   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4802   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4803   PetscFunctionReturn(PETSC_SUCCESS);
4804 }
4805 
4806 /*@
4807    MatDuplicate - Duplicates a matrix including the non-zero structure.
4808 
4809    Collective
4810 
4811    Input Parameters:
4812 +  mat - the matrix
4813 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4814         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4815 
4816    Output Parameter:
4817 .  M - pointer to place new matrix
4818 
4819    Level: intermediate
4820 
4821    Notes:
4822     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4823 
4824     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.
4825 
4826     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
4827     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4828     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4829 
4830 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4831 @*/
4832 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4833 {
4834   Mat         B;
4835   VecType     vtype;
4836   PetscInt    i;
4837   PetscObject dm;
4838   void (*viewf)(void);
4839 
4840   PetscFunctionBegin;
4841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4842   PetscValidType(mat, 1);
4843   PetscValidPointer(M, 3);
4844   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4845   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4846   MatCheckPreallocated(mat, 1);
4847 
4848   *M = NULL;
4849   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4850   PetscUseTypeMethod(mat, duplicate, op, M);
4851   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4852   B = *M;
4853 
4854   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4855   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4856   PetscCall(MatGetVecType(mat, &vtype));
4857   PetscCall(MatSetVecType(B, vtype));
4858 
4859   B->stencil.dim = mat->stencil.dim;
4860   B->stencil.noc = mat->stencil.noc;
4861   for (i = 0; i <= mat->stencil.dim; i++) {
4862     B->stencil.dims[i]   = mat->stencil.dims[i];
4863     B->stencil.starts[i] = mat->stencil.starts[i];
4864   }
4865 
4866   B->nooffproczerorows = mat->nooffproczerorows;
4867   B->nooffprocentries  = mat->nooffprocentries;
4868 
4869   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4870   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4871   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4872   PetscFunctionReturn(PETSC_SUCCESS);
4873 }
4874 
4875 /*@
4876    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4877 
4878    Logically Collective
4879 
4880    Input Parameter:
4881 .  mat - the matrix
4882 
4883    Output Parameter:
4884 .  v - the diagonal of the matrix
4885 
4886    Level: intermediate
4887 
4888    Note:
4889    Currently only correct in parallel for square matrices.
4890 
4891 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4892 @*/
4893 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4894 {
4895   PetscFunctionBegin;
4896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4897   PetscValidType(mat, 1);
4898   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4899   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4900   MatCheckPreallocated(mat, 1);
4901 
4902   PetscUseTypeMethod(mat, getdiagonal, v);
4903   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4904   PetscFunctionReturn(PETSC_SUCCESS);
4905 }
4906 
4907 /*@C
4908    MatGetRowMin - Gets the minimum value (of the real part) of each
4909         row of the matrix
4910 
4911    Logically Collective
4912 
4913    Input Parameter:
4914 .  mat - the matrix
4915 
4916    Output Parameters:
4917 +  v - the vector for storing the maximums
4918 -  idx - the indices of the column found for each row (optional)
4919 
4920    Level: intermediate
4921 
4922    Note:
4923     The result of this call are the same as if one converted the matrix to dense format
4924       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4925 
4926     This code is only implemented for a couple of matrix formats.
4927 
4928 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4929           `MatGetRowMax()`
4930 @*/
4931 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4932 {
4933   PetscFunctionBegin;
4934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4935   PetscValidType(mat, 1);
4936   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4937   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4938 
4939   if (!mat->cmap->N) {
4940     PetscCall(VecSet(v, PETSC_MAX_REAL));
4941     if (idx) {
4942       PetscInt i, m = mat->rmap->n;
4943       for (i = 0; i < m; i++) idx[i] = -1;
4944     }
4945   } else {
4946     MatCheckPreallocated(mat, 1);
4947   }
4948   PetscUseTypeMethod(mat, getrowmin, v, idx);
4949   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4950   PetscFunctionReturn(PETSC_SUCCESS);
4951 }
4952 
4953 /*@C
4954    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4955         row of the matrix
4956 
4957    Logically Collective
4958 
4959    Input Parameter:
4960 .  mat - the matrix
4961 
4962    Output Parameters:
4963 +  v - the vector for storing the minimums
4964 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4965 
4966    Level: intermediate
4967 
4968    Notes:
4969     if a row is completely empty or has only 0.0 values then the idx[] value for that
4970     row is 0 (the first column).
4971 
4972     This code is only implemented for a couple of matrix formats.
4973 
4974 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4975 @*/
4976 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4977 {
4978   PetscFunctionBegin;
4979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4980   PetscValidType(mat, 1);
4981   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4982   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4983   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4984 
4985   if (!mat->cmap->N) {
4986     PetscCall(VecSet(v, 0.0));
4987     if (idx) {
4988       PetscInt i, m = mat->rmap->n;
4989       for (i = 0; i < m; i++) idx[i] = -1;
4990     }
4991   } else {
4992     MatCheckPreallocated(mat, 1);
4993     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4994     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4995   }
4996   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4997   PetscFunctionReturn(PETSC_SUCCESS);
4998 }
4999 
5000 /*@C
5001    MatGetRowMax - Gets the maximum value (of the real part) of each
5002         row of the matrix
5003 
5004    Logically Collective
5005 
5006    Input Parameter:
5007 .  mat - the matrix
5008 
5009    Output Parameters:
5010 +  v - the vector for storing the maximums
5011 -  idx - the indices of the column found for each row (optional)
5012 
5013    Level: intermediate
5014 
5015    Notes:
5016     The result of this call are the same as if one converted the matrix to dense format
5017       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5018 
5019     This code is only implemented for a couple of matrix formats.
5020 
5021 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5022 @*/
5023 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5024 {
5025   PetscFunctionBegin;
5026   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5027   PetscValidType(mat, 1);
5028   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5029   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5030 
5031   if (!mat->cmap->N) {
5032     PetscCall(VecSet(v, PETSC_MIN_REAL));
5033     if (idx) {
5034       PetscInt i, m = mat->rmap->n;
5035       for (i = 0; i < m; i++) idx[i] = -1;
5036     }
5037   } else {
5038     MatCheckPreallocated(mat, 1);
5039     PetscUseTypeMethod(mat, getrowmax, v, idx);
5040   }
5041   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5042   PetscFunctionReturn(PETSC_SUCCESS);
5043 }
5044 
5045 /*@C
5046    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5047         row of the matrix
5048 
5049    Logically Collective
5050 
5051    Input Parameter:
5052 .  mat - the matrix
5053 
5054    Output Parameters:
5055 +  v - the vector for storing the maximums
5056 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5057 
5058    Level: intermediate
5059 
5060    Notes:
5061     if a row is completely empty or has only 0.0 values then the idx[] value for that
5062     row is 0 (the first column).
5063 
5064     This code is only implemented for a couple of matrix formats.
5065 
5066 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5067 @*/
5068 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5069 {
5070   PetscFunctionBegin;
5071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5072   PetscValidType(mat, 1);
5073   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5074   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5075 
5076   if (!mat->cmap->N) {
5077     PetscCall(VecSet(v, 0.0));
5078     if (idx) {
5079       PetscInt i, m = mat->rmap->n;
5080       for (i = 0; i < m; i++) idx[i] = -1;
5081     }
5082   } else {
5083     MatCheckPreallocated(mat, 1);
5084     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5085     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5086   }
5087   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5088   PetscFunctionReturn(PETSC_SUCCESS);
5089 }
5090 
5091 /*@
5092    MatGetRowSum - Gets the sum of each row of the matrix
5093 
5094    Logically or Neighborhood Collective
5095 
5096    Input Parameter:
5097 .  mat - the matrix
5098 
5099    Output Parameter:
5100 .  v - the vector for storing the sum of rows
5101 
5102    Level: intermediate
5103 
5104    Notes:
5105     This code is slow since it is not currently specialized for different formats
5106 
5107 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5108 @*/
5109 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5110 {
5111   Vec ones;
5112 
5113   PetscFunctionBegin;
5114   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5115   PetscValidType(mat, 1);
5116   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5117   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5118   MatCheckPreallocated(mat, 1);
5119   PetscCall(MatCreateVecs(mat, &ones, NULL));
5120   PetscCall(VecSet(ones, 1.));
5121   PetscCall(MatMult(mat, ones, v));
5122   PetscCall(VecDestroy(&ones));
5123   PetscFunctionReturn(PETSC_SUCCESS);
5124 }
5125 
5126 /*@
5127    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5128    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5129 
5130    Collective
5131 
5132    Input Parameter:
5133 .  mat - the matrix to provide the transpose
5134 
5135    Output Parameter:
5136 .  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
5137 
5138    Level: advanced
5139 
5140    Note:
5141    Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5142    routine allows bypassing that call.
5143 
5144 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5145 @*/
5146 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5147 {
5148   PetscContainer  rB = NULL;
5149   MatParentState *rb = NULL;
5150 
5151   PetscFunctionBegin;
5152   PetscCall(PetscNew(&rb));
5153   rb->id    = ((PetscObject)mat)->id;
5154   rb->state = 0;
5155   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5156   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5157   PetscCall(PetscContainerSetPointer(rB, rb));
5158   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5159   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5160   PetscCall(PetscObjectDereference((PetscObject)rB));
5161   PetscFunctionReturn(PETSC_SUCCESS);
5162 }
5163 
5164 /*@
5165    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5166 
5167    Collective
5168 
5169    Input Parameters:
5170 +  mat - the matrix to transpose
5171 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5172 
5173    Output Parameter:
5174 .  B - the transpose
5175 
5176    Level: intermediate
5177 
5178    Notes:
5179      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5180 
5181      `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
5182      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5183 
5184      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.
5185 
5186      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5187 
5188      If mat is unchanged from the last call this function returns immediately without recomputing the result
5189 
5190      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5191 
5192 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5193           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5194 @*/
5195 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5196 {
5197   PetscContainer  rB = NULL;
5198   MatParentState *rb = NULL;
5199 
5200   PetscFunctionBegin;
5201   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5202   PetscValidType(mat, 1);
5203   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5204   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5205   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5206   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5207   MatCheckPreallocated(mat, 1);
5208   if (reuse == MAT_REUSE_MATRIX) {
5209     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5210     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5211     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5212     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5213     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5214   }
5215 
5216   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5217   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5218     PetscUseTypeMethod(mat, transpose, reuse, B);
5219     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5220   }
5221   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5222 
5223   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5224   if (reuse != MAT_INPLACE_MATRIX) {
5225     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5226     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5227     rb->state        = ((PetscObject)mat)->state;
5228     rb->nonzerostate = mat->nonzerostate;
5229   }
5230   PetscFunctionReturn(PETSC_SUCCESS);
5231 }
5232 
5233 /*@
5234    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5235 
5236    Collective
5237 
5238    Input Parameter:
5239 .  A - the matrix to transpose
5240 
5241    Output Parameter:
5242 .  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
5243       numerical portion.
5244 
5245    Level: intermediate
5246 
5247    Note:
5248    This is not supported for many matrix types, use `MatTranspose()` in those cases
5249 
5250 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5251 @*/
5252 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5253 {
5254   PetscFunctionBegin;
5255   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5256   PetscValidType(A, 1);
5257   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5258   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5259   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5260   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5261   PetscCall((*A->ops->transposesymbolic)(A, B));
5262   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5263 
5264   PetscCall(MatTransposeSetPrecursor(A, *B));
5265   PetscFunctionReturn(PETSC_SUCCESS);
5266 }
5267 
5268 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5269 {
5270   PetscContainer  rB;
5271   MatParentState *rb;
5272 
5273   PetscFunctionBegin;
5274   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5275   PetscValidType(A, 1);
5276   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5277   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5278   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5279   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5280   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5281   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5282   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5283   PetscFunctionReturn(PETSC_SUCCESS);
5284 }
5285 
5286 /*@
5287    MatIsTranspose - Test whether a matrix is another one's transpose,
5288         or its own, in which case it tests symmetry.
5289 
5290    Collective
5291 
5292    Input Parameters:
5293 +  A - the matrix to test
5294 .  B - the matrix to test against, this can equal the first parameter
5295 -  tol - tolerance, differences between entries smaller than this are counted as zero
5296 
5297    Output Parameter:
5298 .  flg - the result
5299 
5300    Level: intermediate
5301 
5302    Notes:
5303    Only available for `MATAIJ` matrices.
5304 
5305    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5306    test involves parallel copies of the block-offdiagonal parts of the matrix.
5307 
5308 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5309 @*/
5310 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5311 {
5312   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5313 
5314   PetscFunctionBegin;
5315   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5316   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5317   PetscValidBoolPointer(flg, 4);
5318   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5319   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5320   *flg = PETSC_FALSE;
5321   if (f && g) {
5322     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5323     PetscCall((*f)(A, B, tol, flg));
5324   } else {
5325     MatType mattype;
5326 
5327     PetscCall(MatGetType(f ? B : A, &mattype));
5328     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5329   }
5330   PetscFunctionReturn(PETSC_SUCCESS);
5331 }
5332 
5333 /*@
5334    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5335 
5336    Collective
5337 
5338    Input Parameters:
5339 +  mat - the matrix to transpose and complex conjugate
5340 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5341 
5342    Output Parameter:
5343 .  B - the Hermitian transpose
5344 
5345    Level: intermediate
5346 
5347 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5348 @*/
5349 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5350 {
5351   PetscFunctionBegin;
5352   PetscCall(MatTranspose(mat, reuse, B));
5353 #if defined(PETSC_USE_COMPLEX)
5354   PetscCall(MatConjugate(*B));
5355 #endif
5356   PetscFunctionReturn(PETSC_SUCCESS);
5357 }
5358 
5359 /*@
5360    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5361 
5362    Collective
5363 
5364    Input Parameters:
5365 +  A - the matrix to test
5366 .  B - the matrix to test against, this can equal the first parameter
5367 -  tol - tolerance, differences between entries smaller than this are counted as zero
5368 
5369    Output Parameter:
5370 .  flg - the result
5371 
5372    Level: intermediate
5373 
5374    Notes:
5375    Only available for `MATAIJ` matrices.
5376 
5377    The sequential algorithm
5378    has a running time of the order of the number of nonzeros; the parallel
5379    test involves parallel copies of the block-offdiagonal parts of the matrix.
5380 
5381 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5382 @*/
5383 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5384 {
5385   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5386 
5387   PetscFunctionBegin;
5388   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5389   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5390   PetscValidBoolPointer(flg, 4);
5391   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5392   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5393   if (f && g) {
5394     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5395     PetscCall((*f)(A, B, tol, flg));
5396   }
5397   PetscFunctionReturn(PETSC_SUCCESS);
5398 }
5399 
5400 /*@
5401    MatPermute - Creates a new matrix with rows and columns permuted from the
5402    original.
5403 
5404    Collective
5405 
5406    Input Parameters:
5407 +  mat - the matrix to permute
5408 .  row - row permutation, each processor supplies only the permutation for its rows
5409 -  col - column permutation, each processor supplies only the permutation for its columns
5410 
5411    Output Parameter:
5412 .  B - the permuted matrix
5413 
5414    Level: advanced
5415 
5416    Note:
5417    The index sets map from row/col of permuted matrix to row/col of original matrix.
5418    The index sets should be on the same communicator as mat and have the same local sizes.
5419 
5420    Developer Note:
5421      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5422      exploit the fact that row and col are permutations, consider implementing the
5423      more general `MatCreateSubMatrix()` instead.
5424 
5425 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5426 @*/
5427 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5428 {
5429   PetscFunctionBegin;
5430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5431   PetscValidType(mat, 1);
5432   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5433   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5434   PetscValidPointer(B, 4);
5435   PetscCheckSameComm(mat, 1, row, 2);
5436   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5439   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5440   MatCheckPreallocated(mat, 1);
5441 
5442   if (mat->ops->permute) {
5443     PetscUseTypeMethod(mat, permute, row, col, B);
5444     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5445   } else {
5446     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5447   }
5448   PetscFunctionReturn(PETSC_SUCCESS);
5449 }
5450 
5451 /*@
5452    MatEqual - Compares two matrices.
5453 
5454    Collective
5455 
5456    Input Parameters:
5457 +  A - the first matrix
5458 -  B - the second matrix
5459 
5460    Output Parameter:
5461 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5462 
5463    Level: intermediate
5464 
5465 .seealso: [](chapter_matrices), `Mat`
5466 @*/
5467 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5468 {
5469   PetscFunctionBegin;
5470   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5471   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5472   PetscValidType(A, 1);
5473   PetscValidType(B, 2);
5474   PetscValidBoolPointer(flg, 3);
5475   PetscCheckSameComm(A, 1, B, 2);
5476   MatCheckPreallocated(A, 1);
5477   MatCheckPreallocated(B, 2);
5478   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5479   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5480   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,
5481              B->cmap->N);
5482   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5483     PetscUseTypeMethod(A, equal, B, flg);
5484   } else {
5485     PetscCall(MatMultEqual(A, B, 10, flg));
5486   }
5487   PetscFunctionReturn(PETSC_SUCCESS);
5488 }
5489 
5490 /*@
5491    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5492    matrices that are stored as vectors.  Either of the two scaling
5493    matrices can be `NULL`.
5494 
5495    Collective
5496 
5497    Input Parameters:
5498 +  mat - the matrix to be scaled
5499 .  l - the left scaling vector (or `NULL`)
5500 -  r - the right scaling vector (or `NULL`)
5501 
5502    Level: intermediate
5503 
5504    Note:
5505    `MatDiagonalScale()` computes A = LAR, where
5506    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5507    The L scales the rows of the matrix, the R scales the columns of the matrix.
5508 
5509 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5510 @*/
5511 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5512 {
5513   PetscFunctionBegin;
5514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5515   PetscValidType(mat, 1);
5516   if (l) {
5517     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5518     PetscCheckSameComm(mat, 1, l, 2);
5519   }
5520   if (r) {
5521     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5522     PetscCheckSameComm(mat, 1, r, 3);
5523   }
5524   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5525   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5526   MatCheckPreallocated(mat, 1);
5527   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5528 
5529   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5530   PetscUseTypeMethod(mat, diagonalscale, l, r);
5531   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5532   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5533   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5534   PetscFunctionReturn(PETSC_SUCCESS);
5535 }
5536 
5537 /*@
5538     MatScale - Scales all elements of a matrix by a given number.
5539 
5540     Logically Collective
5541 
5542     Input Parameters:
5543 +   mat - the matrix to be scaled
5544 -   a  - the scaling value
5545 
5546     Level: intermediate
5547 
5548 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5549 @*/
5550 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5551 {
5552   PetscFunctionBegin;
5553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5554   PetscValidType(mat, 1);
5555   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5556   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5557   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5558   PetscValidLogicalCollectiveScalar(mat, a, 2);
5559   MatCheckPreallocated(mat, 1);
5560 
5561   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5562   if (a != (PetscScalar)1.0) {
5563     PetscUseTypeMethod(mat, scale, a);
5564     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5565   }
5566   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5567   PetscFunctionReturn(PETSC_SUCCESS);
5568 }
5569 
5570 /*@
5571    MatNorm - Calculates various norms of a matrix.
5572 
5573    Collective
5574 
5575    Input Parameters:
5576 +  mat - the matrix
5577 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5578 
5579    Output Parameter:
5580 .  nrm - the resulting norm
5581 
5582    Level: intermediate
5583 
5584 .seealso: [](chapter_matrices), `Mat`
5585 @*/
5586 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5587 {
5588   PetscFunctionBegin;
5589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5590   PetscValidType(mat, 1);
5591   PetscValidRealPointer(nrm, 3);
5592 
5593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5594   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5595   MatCheckPreallocated(mat, 1);
5596 
5597   PetscUseTypeMethod(mat, norm, type, nrm);
5598   PetscFunctionReturn(PETSC_SUCCESS);
5599 }
5600 
5601 /*
5602      This variable is used to prevent counting of MatAssemblyBegin() that
5603    are called from within a MatAssemblyEnd().
5604 */
5605 static PetscInt MatAssemblyEnd_InUse = 0;
5606 /*@
5607    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5608    be called after completing all calls to `MatSetValues()`.
5609 
5610    Collective
5611 
5612    Input Parameters:
5613 +  mat - the matrix
5614 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5615 
5616    Level: beginner
5617 
5618    Notes:
5619    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5620    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5621 
5622    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5623    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5624    using the matrix.
5625 
5626    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5627    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
5628    a global collective operation requiring all processes that share the matrix.
5629 
5630    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5631    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5632    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5633 
5634 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5635 @*/
5636 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5637 {
5638   PetscFunctionBegin;
5639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5640   PetscValidType(mat, 1);
5641   MatCheckPreallocated(mat, 1);
5642   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5643   if (mat->assembled) {
5644     mat->was_assembled = PETSC_TRUE;
5645     mat->assembled     = PETSC_FALSE;
5646   }
5647 
5648   if (!MatAssemblyEnd_InUse) {
5649     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5650     PetscTryTypeMethod(mat, assemblybegin, type);
5651     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5652   } else PetscTryTypeMethod(mat, assemblybegin, type);
5653   PetscFunctionReturn(PETSC_SUCCESS);
5654 }
5655 
5656 /*@
5657    MatAssembled - Indicates if a matrix has been assembled and is ready for
5658      use; for example, in matrix-vector product.
5659 
5660    Not Collective
5661 
5662    Input Parameter:
5663 .  mat - the matrix
5664 
5665    Output Parameter:
5666 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5667 
5668    Level: advanced
5669 
5670 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5671 @*/
5672 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5673 {
5674   PetscFunctionBegin;
5675   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5676   PetscValidBoolPointer(assembled, 2);
5677   *assembled = mat->assembled;
5678   PetscFunctionReturn(PETSC_SUCCESS);
5679 }
5680 
5681 /*@
5682    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5683    be called after `MatAssemblyBegin()`.
5684 
5685    Collective
5686 
5687    Input Parameters:
5688 +  mat - the matrix
5689 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5690 
5691    Options Database Keys:
5692 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5693 .  -mat_view ::ascii_info_detail - Prints more detailed info
5694 .  -mat_view - Prints matrix in ASCII format
5695 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5696 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5697 .  -display <name> - Sets display name (default is host)
5698 .  -draw_pause <sec> - Sets number of seconds to pause after display
5699 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5700 .  -viewer_socket_machine <machine> - Machine to use for socket
5701 .  -viewer_socket_port <port> - Port number to use for socket
5702 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5703 
5704    Level: beginner
5705 
5706 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5707 @*/
5708 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5709 {
5710   static PetscInt inassm = 0;
5711   PetscBool       flg    = PETSC_FALSE;
5712 
5713   PetscFunctionBegin;
5714   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5715   PetscValidType(mat, 1);
5716 
5717   inassm++;
5718   MatAssemblyEnd_InUse++;
5719   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5720     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5721     PetscTryTypeMethod(mat, assemblyend, type);
5722     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5723   } else PetscTryTypeMethod(mat, assemblyend, type);
5724 
5725   /* Flush assembly is not a true assembly */
5726   if (type != MAT_FLUSH_ASSEMBLY) {
5727     if (mat->num_ass) {
5728       if (!mat->symmetry_eternal) {
5729         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5730         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5731       }
5732       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5733       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5734     }
5735     mat->num_ass++;
5736     mat->assembled        = PETSC_TRUE;
5737     mat->ass_nonzerostate = mat->nonzerostate;
5738   }
5739 
5740   mat->insertmode = NOT_SET_VALUES;
5741   MatAssemblyEnd_InUse--;
5742   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5743   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5744     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5745 
5746     if (mat->checksymmetryonassembly) {
5747       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5748       if (flg) {
5749         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5750       } else {
5751         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5752       }
5753     }
5754     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5755   }
5756   inassm--;
5757   PetscFunctionReturn(PETSC_SUCCESS);
5758 }
5759 
5760 /*@
5761    MatSetOption - Sets a parameter option for a matrix. Some options
5762    may be specific to certain storage formats.  Some options
5763    determine how values will be inserted (or added). Sorted,
5764    row-oriented input will generally assemble the fastest. The default
5765    is row-oriented.
5766 
5767    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5768 
5769    Input Parameters:
5770 +  mat - the matrix
5771 .  option - the option, one of those listed below (and possibly others),
5772 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5773 
5774   Options Describing Matrix Structure:
5775 +    `MAT_SPD` - symmetric positive definite
5776 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5777 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5778 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5779 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5780 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5781 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5782 
5783    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5784    do not need to be computed (usually at a high cost)
5785 
5786    Options For Use with `MatSetValues()`:
5787    Insert a logically dense subblock, which can be
5788 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5789 
5790    These options reflect the data you pass in with `MatSetValues()`; it has
5791    nothing to do with how the data is stored internally in the matrix
5792    data structure.
5793 
5794    When (re)assembling a matrix, we can restrict the input for
5795    efficiency/debugging purposes.  These options include
5796 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5797 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5798 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5799 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5800 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5801 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5802         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5803         performance for very large process counts.
5804 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5805         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5806         functions, instead sending only neighbor messages.
5807 
5808    Level: intermediate
5809 
5810    Notes:
5811    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5812 
5813    Some options are relevant only for particular matrix types and
5814    are thus ignored by others.  Other options are not supported by
5815    certain matrix types and will generate an error message if set.
5816 
5817    If using Fortran to compute a matrix, one may need to
5818    use the column-oriented option (or convert to the row-oriented
5819    format).
5820 
5821    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5822    that would generate a new entry in the nonzero structure is instead
5823    ignored.  Thus, if memory has not already been allocated for this particular
5824    data, then the insertion is ignored. For dense matrices, in which
5825    the entire array is allocated, no entries are ever ignored.
5826    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5827 
5828    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5829    that would generate a new entry in the nonzero structure instead produces
5830    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
5831 
5832    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5833    that would generate a new entry that has not been preallocated will
5834    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5835    only.) This is a useful flag when debugging matrix memory preallocation.
5836    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5837 
5838    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5839    other processors should be dropped, rather than stashed.
5840    This is useful if you know that the "owning" processor is also
5841    always generating the correct matrix entries, so that PETSc need
5842    not transfer duplicate entries generated on another processor.
5843 
5844    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5845    searches during matrix assembly. When this flag is set, the hash table
5846    is created during the first matrix assembly. This hash table is
5847    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5848    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5849    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5850    supported by `MATMPIBAIJ` format only.
5851 
5852    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5853    are kept in the nonzero structure
5854 
5855    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5856    a zero location in the matrix
5857 
5858    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5859 
5860    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5861         zero row routines and thus improves performance for very large process counts.
5862 
5863    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5864         part of the matrix (since they should match the upper triangular part).
5865 
5866    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5867                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5868                      with finite difference schemes with non-periodic boundary conditions.
5869 
5870    Developer Note:
5871    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5872    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5873    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5874    not changed.
5875 
5876 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5877 @*/
5878 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5879 {
5880   PetscFunctionBegin;
5881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5882   if (op > 0) {
5883     PetscValidLogicalCollectiveEnum(mat, op, 2);
5884     PetscValidLogicalCollectiveBool(mat, flg, 3);
5885   }
5886 
5887   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);
5888 
5889   switch (op) {
5890   case MAT_FORCE_DIAGONAL_ENTRIES:
5891     mat->force_diagonals = flg;
5892     PetscFunctionReturn(PETSC_SUCCESS);
5893   case MAT_NO_OFF_PROC_ENTRIES:
5894     mat->nooffprocentries = flg;
5895     PetscFunctionReturn(PETSC_SUCCESS);
5896   case MAT_SUBSET_OFF_PROC_ENTRIES:
5897     mat->assembly_subset = flg;
5898     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5899 #if !defined(PETSC_HAVE_MPIUNI)
5900       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5901 #endif
5902       mat->stash.first_assembly_done = PETSC_FALSE;
5903     }
5904     PetscFunctionReturn(PETSC_SUCCESS);
5905   case MAT_NO_OFF_PROC_ZERO_ROWS:
5906     mat->nooffproczerorows = flg;
5907     PetscFunctionReturn(PETSC_SUCCESS);
5908   case MAT_SPD:
5909     if (flg) {
5910       mat->spd                    = PETSC_BOOL3_TRUE;
5911       mat->symmetric              = PETSC_BOOL3_TRUE;
5912       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5913     } else {
5914       mat->spd = PETSC_BOOL3_FALSE;
5915     }
5916     break;
5917   case MAT_SYMMETRIC:
5918     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5919     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5920 #if !defined(PETSC_USE_COMPLEX)
5921     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5922 #endif
5923     break;
5924   case MAT_HERMITIAN:
5925     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5926     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5927 #if !defined(PETSC_USE_COMPLEX)
5928     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5929 #endif
5930     break;
5931   case MAT_STRUCTURALLY_SYMMETRIC:
5932     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5933     break;
5934   case MAT_SYMMETRY_ETERNAL:
5935     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");
5936     mat->symmetry_eternal = flg;
5937     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5938     break;
5939   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5940     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");
5941     mat->structural_symmetry_eternal = flg;
5942     break;
5943   case MAT_SPD_ETERNAL:
5944     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");
5945     mat->spd_eternal = flg;
5946     if (flg) {
5947       mat->structural_symmetry_eternal = PETSC_TRUE;
5948       mat->symmetry_eternal            = PETSC_TRUE;
5949     }
5950     break;
5951   case MAT_STRUCTURE_ONLY:
5952     mat->structure_only = flg;
5953     break;
5954   case MAT_SORTED_FULL:
5955     mat->sortedfull = flg;
5956     break;
5957   default:
5958     break;
5959   }
5960   PetscTryTypeMethod(mat, setoption, op, flg);
5961   PetscFunctionReturn(PETSC_SUCCESS);
5962 }
5963 
5964 /*@
5965    MatGetOption - Gets a parameter option that has been set for a matrix.
5966 
5967    Logically Collective
5968 
5969    Input Parameters:
5970 +  mat - the matrix
5971 -  option - the option, this only responds to certain options, check the code for which ones
5972 
5973    Output Parameter:
5974 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5975 
5976    Level: intermediate
5977 
5978     Notes:
5979     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5980 
5981     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5982     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5983 
5984 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5985     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5986 @*/
5987 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5988 {
5989   PetscFunctionBegin;
5990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5991   PetscValidType(mat, 1);
5992 
5993   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);
5994   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()");
5995 
5996   switch (op) {
5997   case MAT_NO_OFF_PROC_ENTRIES:
5998     *flg = mat->nooffprocentries;
5999     break;
6000   case MAT_NO_OFF_PROC_ZERO_ROWS:
6001     *flg = mat->nooffproczerorows;
6002     break;
6003   case MAT_SYMMETRIC:
6004     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6005     break;
6006   case MAT_HERMITIAN:
6007     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6008     break;
6009   case MAT_STRUCTURALLY_SYMMETRIC:
6010     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6011     break;
6012   case MAT_SPD:
6013     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6014     break;
6015   case MAT_SYMMETRY_ETERNAL:
6016     *flg = mat->symmetry_eternal;
6017     break;
6018   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6019     *flg = mat->symmetry_eternal;
6020     break;
6021   default:
6022     break;
6023   }
6024   PetscFunctionReturn(PETSC_SUCCESS);
6025 }
6026 
6027 /*@
6028    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6029    this routine retains the old nonzero structure.
6030 
6031    Logically Collective
6032 
6033    Input Parameter:
6034 .  mat - the matrix
6035 
6036    Level: intermediate
6037 
6038    Note:
6039     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.
6040    See the Performance chapter of the users manual for information on preallocating matrices.
6041 
6042 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6043 @*/
6044 PetscErrorCode MatZeroEntries(Mat mat)
6045 {
6046   PetscFunctionBegin;
6047   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6048   PetscValidType(mat, 1);
6049   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6050   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");
6051   MatCheckPreallocated(mat, 1);
6052 
6053   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6054   PetscUseTypeMethod(mat, zeroentries);
6055   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6056   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6057   PetscFunctionReturn(PETSC_SUCCESS);
6058 }
6059 
6060 /*@
6061    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6062    of a set of rows and columns of a matrix.
6063 
6064    Collective
6065 
6066    Input Parameters:
6067 +  mat - the matrix
6068 .  numRows - the number of rows/columns to zero
6069 .  rows - the global row indices
6070 .  diag - value put in the diagonal of the eliminated rows
6071 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6072 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6073 
6074    Level: intermediate
6075 
6076    Notes:
6077    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6078 
6079    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6080    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
6081 
6082    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6083    Krylov method to take advantage of the known solution on the zeroed rows.
6084 
6085    For the parallel case, all processes that share the matrix (i.e.,
6086    those in the communicator used for matrix creation) MUST call this
6087    routine, regardless of whether any rows being zeroed are owned by
6088    them.
6089 
6090    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6091 
6092    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6093    list only rows local to itself).
6094 
6095    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6096 
6097 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6098           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6099 @*/
6100 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6101 {
6102   PetscFunctionBegin;
6103   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6104   PetscValidType(mat, 1);
6105   if (numRows) PetscValidIntPointer(rows, 3);
6106   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6107   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6108   MatCheckPreallocated(mat, 1);
6109 
6110   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6111   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6112   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6113   PetscFunctionReturn(PETSC_SUCCESS);
6114 }
6115 
6116 /*@
6117    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6118    of a set of rows and columns of a matrix.
6119 
6120    Collective
6121 
6122    Input Parameters:
6123 +  mat - the matrix
6124 .  is - the rows to zero
6125 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6126 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6127 -  b - optional vector of right hand side, that will be adjusted by provided solution
6128 
6129    Level: intermediate
6130 
6131    Note:
6132    See `MatZeroRowsColumns()` for details on how this routine operates.
6133 
6134 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6135           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6136 @*/
6137 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6138 {
6139   PetscInt        numRows;
6140   const PetscInt *rows;
6141 
6142   PetscFunctionBegin;
6143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6144   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6145   PetscValidType(mat, 1);
6146   PetscValidType(is, 2);
6147   PetscCall(ISGetLocalSize(is, &numRows));
6148   PetscCall(ISGetIndices(is, &rows));
6149   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6150   PetscCall(ISRestoreIndices(is, &rows));
6151   PetscFunctionReturn(PETSC_SUCCESS);
6152 }
6153 
6154 /*@
6155    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6156    of a set of rows of a matrix.
6157 
6158    Collective
6159 
6160    Input Parameters:
6161 +  mat - the matrix
6162 .  numRows - the number of rows to zero
6163 .  rows - the global row indices
6164 .  diag - value put in the diagonal of the zeroed rows
6165 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6166 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6167 
6168    Level: intermediate
6169 
6170    Notes:
6171    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6172 
6173    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6174 
6175    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6176    Krylov method to take advantage of the known solution on the zeroed rows.
6177 
6178    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6179    from the matrix.
6180 
6181    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6182    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
6183    formats this does not alter the nonzero structure.
6184 
6185    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6186    of the matrix is not changed the values are
6187    merely zeroed.
6188 
6189    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6190    formats can optionally remove the main diagonal entry from the
6191    nonzero structure as well, by passing 0.0 as the final argument).
6192 
6193    For the parallel case, all processes that share the matrix (i.e.,
6194    those in the communicator used for matrix creation) MUST call this
6195    routine, regardless of whether any rows being zeroed are owned by
6196    them.
6197 
6198    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6199    list only rows local to itself).
6200 
6201    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6202    owns that are to be zeroed. This saves a global synchronization in the implementation.
6203 
6204 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6205           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6206 @*/
6207 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6208 {
6209   PetscFunctionBegin;
6210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6211   PetscValidType(mat, 1);
6212   if (numRows) PetscValidIntPointer(rows, 3);
6213   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6214   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6215   MatCheckPreallocated(mat, 1);
6216 
6217   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6218   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6219   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6220   PetscFunctionReturn(PETSC_SUCCESS);
6221 }
6222 
6223 /*@
6224    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6225    of a set of rows of a matrix.
6226 
6227    Collective
6228 
6229    Input Parameters:
6230 +  mat - the matrix
6231 .  is - index set of rows to remove (if `NULL` then no row is removed)
6232 .  diag - value put in all diagonals of eliminated rows
6233 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6234 -  b - optional vector of right hand side, that will be adjusted by provided solution
6235 
6236    Level: intermediate
6237 
6238    Note:
6239    See `MatZeroRows()` for details on how this routine operates.
6240 
6241 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6242           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6243 @*/
6244 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6245 {
6246   PetscInt        numRows = 0;
6247   const PetscInt *rows    = NULL;
6248 
6249   PetscFunctionBegin;
6250   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6251   PetscValidType(mat, 1);
6252   if (is) {
6253     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6254     PetscCall(ISGetLocalSize(is, &numRows));
6255     PetscCall(ISGetIndices(is, &rows));
6256   }
6257   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6258   if (is) PetscCall(ISRestoreIndices(is, &rows));
6259   PetscFunctionReturn(PETSC_SUCCESS);
6260 }
6261 
6262 /*@
6263    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6264    of a set of rows of a matrix. These rows must be local to the process.
6265 
6266    Collective
6267 
6268    Input Parameters:
6269 +  mat - the matrix
6270 .  numRows - the number of rows to remove
6271 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6272 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6273 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6274 -  b - optional vector of right hand side, that will be adjusted by provided solution
6275 
6276    Level: intermediate
6277 
6278    Notes:
6279    See `MatZeroRows()` for details on how this routine operates.
6280 
6281    The grid coordinates are across the entire grid, not just the local portion
6282 
6283    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6284    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6285    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6286    `DM_BOUNDARY_PERIODIC` boundary type.
6287 
6288    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
6289    a single value per point) you can skip filling those indices.
6290 
6291    Fortran Note:
6292    `idxm` and `idxn` should be declared as
6293 $     MatStencil idxm(4,m)
6294    and the values inserted using
6295 .vb
6296     idxm(MatStencil_i,1) = i
6297     idxm(MatStencil_j,1) = j
6298     idxm(MatStencil_k,1) = k
6299     idxm(MatStencil_c,1) = c
6300    etc
6301 .ve
6302 
6303 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6304           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6305 @*/
6306 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6307 {
6308   PetscInt  dim    = mat->stencil.dim;
6309   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6310   PetscInt *dims   = mat->stencil.dims + 1;
6311   PetscInt *starts = mat->stencil.starts;
6312   PetscInt *dxm    = (PetscInt *)rows;
6313   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6314 
6315   PetscFunctionBegin;
6316   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6317   PetscValidType(mat, 1);
6318   if (numRows) PetscValidPointer(rows, 3);
6319 
6320   PetscCall(PetscMalloc1(numRows, &jdxm));
6321   for (i = 0; i < numRows; ++i) {
6322     /* Skip unused dimensions (they are ordered k, j, i, c) */
6323     for (j = 0; j < 3 - sdim; ++j) dxm++;
6324     /* Local index in X dir */
6325     tmp = *dxm++ - starts[0];
6326     /* Loop over remaining dimensions */
6327     for (j = 0; j < dim - 1; ++j) {
6328       /* If nonlocal, set index to be negative */
6329       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6330       /* Update local index */
6331       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6332     }
6333     /* Skip component slot if necessary */
6334     if (mat->stencil.noc) dxm++;
6335     /* Local row number */
6336     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6337   }
6338   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6339   PetscCall(PetscFree(jdxm));
6340   PetscFunctionReturn(PETSC_SUCCESS);
6341 }
6342 
6343 /*@
6344    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6345    of a set of rows and columns of a matrix.
6346 
6347    Collective
6348 
6349    Input Parameters:
6350 +  mat - the matrix
6351 .  numRows - the number of rows/columns to remove
6352 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6353 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6354 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6355 -  b - optional vector of right hand side, that will be adjusted by provided solution
6356 
6357    Level: intermediate
6358 
6359    Notes:
6360    See `MatZeroRowsColumns()` for details on how this routine operates.
6361 
6362    The grid coordinates are across the entire grid, not just the local portion
6363 
6364    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6365    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6366    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6367    `DM_BOUNDARY_PERIODIC` boundary type.
6368 
6369    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
6370    a single value per point) you can skip filling those indices.
6371 
6372    Fortran Note:
6373    `idxm` and `idxn` should be declared as
6374 $     MatStencil idxm(4,m)
6375    and the values inserted using
6376 .vb
6377     idxm(MatStencil_i,1) = i
6378     idxm(MatStencil_j,1) = j
6379     idxm(MatStencil_k,1) = k
6380     idxm(MatStencil_c,1) = c
6381     etc
6382 .ve
6383 
6384 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6385           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6386 @*/
6387 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6388 {
6389   PetscInt  dim    = mat->stencil.dim;
6390   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6391   PetscInt *dims   = mat->stencil.dims + 1;
6392   PetscInt *starts = mat->stencil.starts;
6393   PetscInt *dxm    = (PetscInt *)rows;
6394   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6395 
6396   PetscFunctionBegin;
6397   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6398   PetscValidType(mat, 1);
6399   if (numRows) PetscValidPointer(rows, 3);
6400 
6401   PetscCall(PetscMalloc1(numRows, &jdxm));
6402   for (i = 0; i < numRows; ++i) {
6403     /* Skip unused dimensions (they are ordered k, j, i, c) */
6404     for (j = 0; j < 3 - sdim; ++j) dxm++;
6405     /* Local index in X dir */
6406     tmp = *dxm++ - starts[0];
6407     /* Loop over remaining dimensions */
6408     for (j = 0; j < dim - 1; ++j) {
6409       /* If nonlocal, set index to be negative */
6410       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6411       /* Update local index */
6412       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6413     }
6414     /* Skip component slot if necessary */
6415     if (mat->stencil.noc) dxm++;
6416     /* Local row number */
6417     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6418   }
6419   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6420   PetscCall(PetscFree(jdxm));
6421   PetscFunctionReturn(PETSC_SUCCESS);
6422 }
6423 
6424 /*@C
6425    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6426    of a set of rows of a matrix; using local numbering of rows.
6427 
6428    Collective
6429 
6430    Input Parameters:
6431 +  mat - the matrix
6432 .  numRows - the number of rows to remove
6433 .  rows - the local row indices
6434 .  diag - value put in all diagonals of eliminated rows
6435 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6436 -  b - optional vector of right hand side, that will be adjusted by provided solution
6437 
6438    Level: intermediate
6439 
6440    Notes:
6441    Before calling `MatZeroRowsLocal()`, the user must first set the
6442    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6443 
6444    See `MatZeroRows()` for details on how this routine operates.
6445 
6446 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6447           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6448 @*/
6449 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6450 {
6451   PetscFunctionBegin;
6452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6453   PetscValidType(mat, 1);
6454   if (numRows) PetscValidIntPointer(rows, 3);
6455   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6456   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6457   MatCheckPreallocated(mat, 1);
6458 
6459   if (mat->ops->zerorowslocal) {
6460     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6461   } else {
6462     IS              is, newis;
6463     const PetscInt *newRows;
6464 
6465     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6466     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6467     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6468     PetscCall(ISGetIndices(newis, &newRows));
6469     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6470     PetscCall(ISRestoreIndices(newis, &newRows));
6471     PetscCall(ISDestroy(&newis));
6472     PetscCall(ISDestroy(&is));
6473   }
6474   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6475   PetscFunctionReturn(PETSC_SUCCESS);
6476 }
6477 
6478 /*@
6479    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6480    of a set of rows of a matrix; using local numbering of rows.
6481 
6482    Collective
6483 
6484    Input Parameters:
6485 +  mat - the matrix
6486 .  is - index set of rows to remove
6487 .  diag - value put in all diagonals of eliminated rows
6488 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6489 -  b - optional vector of right hand side, that will be adjusted by provided solution
6490 
6491    Level: intermediate
6492 
6493    Notes:
6494    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6495    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6496 
6497    See `MatZeroRows()` for details on how this routine operates.
6498 
6499 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6500           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6501 @*/
6502 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6503 {
6504   PetscInt        numRows;
6505   const PetscInt *rows;
6506 
6507   PetscFunctionBegin;
6508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6509   PetscValidType(mat, 1);
6510   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6511   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6512   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6513   MatCheckPreallocated(mat, 1);
6514 
6515   PetscCall(ISGetLocalSize(is, &numRows));
6516   PetscCall(ISGetIndices(is, &rows));
6517   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6518   PetscCall(ISRestoreIndices(is, &rows));
6519   PetscFunctionReturn(PETSC_SUCCESS);
6520 }
6521 
6522 /*@
6523    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6524    of a set of rows and columns of a matrix; using local numbering of rows.
6525 
6526    Collective
6527 
6528    Input Parameters:
6529 +  mat - the matrix
6530 .  numRows - the number of rows to remove
6531 .  rows - the global row indices
6532 .  diag - value put in all diagonals of eliminated rows
6533 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6534 -  b - optional vector of right hand side, that will be adjusted by provided solution
6535 
6536    Level: intermediate
6537 
6538    Notes:
6539    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6540    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6541 
6542    See `MatZeroRowsColumns()` for details on how this routine operates.
6543 
6544 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6545           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6546 @*/
6547 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6548 {
6549   IS              is, newis;
6550   const PetscInt *newRows;
6551 
6552   PetscFunctionBegin;
6553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6554   PetscValidType(mat, 1);
6555   if (numRows) PetscValidIntPointer(rows, 3);
6556   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6557   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6558   MatCheckPreallocated(mat, 1);
6559 
6560   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6561   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6562   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6563   PetscCall(ISGetIndices(newis, &newRows));
6564   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6565   PetscCall(ISRestoreIndices(newis, &newRows));
6566   PetscCall(ISDestroy(&newis));
6567   PetscCall(ISDestroy(&is));
6568   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6569   PetscFunctionReturn(PETSC_SUCCESS);
6570 }
6571 
6572 /*@
6573    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6574    of a set of rows and columns of a matrix; using local numbering of rows.
6575 
6576    Collective
6577 
6578    Input Parameters:
6579 +  mat - the matrix
6580 .  is - index set of rows to remove
6581 .  diag - value put in all diagonals of eliminated rows
6582 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6583 -  b - optional vector of right hand side, that will be adjusted by provided solution
6584 
6585    Level: intermediate
6586 
6587    Notes:
6588    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6589    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6590 
6591    See `MatZeroRowsColumns()` for details on how this routine operates.
6592 
6593 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6594           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6595 @*/
6596 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6597 {
6598   PetscInt        numRows;
6599   const PetscInt *rows;
6600 
6601   PetscFunctionBegin;
6602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6603   PetscValidType(mat, 1);
6604   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6605   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6606   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6607   MatCheckPreallocated(mat, 1);
6608 
6609   PetscCall(ISGetLocalSize(is, &numRows));
6610   PetscCall(ISGetIndices(is, &rows));
6611   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6612   PetscCall(ISRestoreIndices(is, &rows));
6613   PetscFunctionReturn(PETSC_SUCCESS);
6614 }
6615 
6616 /*@C
6617    MatGetSize - Returns the numbers of rows and columns in a matrix.
6618 
6619    Not Collective
6620 
6621    Input Parameter:
6622 .  mat - the matrix
6623 
6624    Output Parameters:
6625 +  m - the number of global rows
6626 -  n - the number of global columns
6627 
6628    Level: beginner
6629 
6630    Note:
6631    Both output parameters can be `NULL` on input.
6632 
6633 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6634 @*/
6635 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6636 {
6637   PetscFunctionBegin;
6638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6639   if (m) *m = mat->rmap->N;
6640   if (n) *n = mat->cmap->N;
6641   PetscFunctionReturn(PETSC_SUCCESS);
6642 }
6643 
6644 /*@C
6645    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6646    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6647 
6648    Not Collective
6649 
6650    Input Parameter:
6651 .  mat - the matrix
6652 
6653    Output Parameters:
6654 +  m - the number of local rows, use `NULL` to not obtain this value
6655 -  n - the number of local columns, use `NULL` to not obtain this value
6656 
6657    Level: beginner
6658 
6659 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6660 @*/
6661 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6662 {
6663   PetscFunctionBegin;
6664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6665   if (m) PetscValidIntPointer(m, 2);
6666   if (n) PetscValidIntPointer(n, 3);
6667   if (m) *m = mat->rmap->n;
6668   if (n) *n = mat->cmap->n;
6669   PetscFunctionReturn(PETSC_SUCCESS);
6670 }
6671 
6672 /*@C
6673    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6674    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6675 
6676    Not Collective, unless matrix has not been allocated, then collective
6677 
6678    Input Parameter:
6679 .  mat - the matrix
6680 
6681    Output Parameters:
6682 +  m - the global index of the first local column, use `NULL` to not obtain this value
6683 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6684 
6685    Level: developer
6686 
6687 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6688 @*/
6689 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6690 {
6691   PetscFunctionBegin;
6692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6693   PetscValidType(mat, 1);
6694   if (m) PetscValidIntPointer(m, 2);
6695   if (n) PetscValidIntPointer(n, 3);
6696   MatCheckPreallocated(mat, 1);
6697   if (m) *m = mat->cmap->rstart;
6698   if (n) *n = mat->cmap->rend;
6699   PetscFunctionReturn(PETSC_SUCCESS);
6700 }
6701 
6702 /*@C
6703    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6704    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
6705    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6706 
6707    Not Collective
6708 
6709    Input Parameter:
6710 .  mat - the matrix
6711 
6712    Output Parameters:
6713 +  m - the global index of the first local row, use `NULL` to not obtain this value
6714 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6715 
6716    Level: beginner
6717 
6718    Note:
6719   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6720   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6721   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6722 
6723 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6724           `PetscLayout`
6725 @*/
6726 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6727 {
6728   PetscFunctionBegin;
6729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6730   PetscValidType(mat, 1);
6731   if (m) PetscValidIntPointer(m, 2);
6732   if (n) PetscValidIntPointer(n, 3);
6733   MatCheckPreallocated(mat, 1);
6734   if (m) *m = mat->rmap->rstart;
6735   if (n) *n = mat->rmap->rend;
6736   PetscFunctionReturn(PETSC_SUCCESS);
6737 }
6738 
6739 /*@C
6740    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6741    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
6742    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6743 
6744    Not Collective, unless matrix has not been allocated
6745 
6746    Input Parameter:
6747 .  mat - the matrix
6748 
6749    Output Parameter:
6750 .  ranges - start of each processors portion plus one more than the total length at the end
6751 
6752    Level: beginner
6753 
6754 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6755 @*/
6756 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6757 {
6758   PetscFunctionBegin;
6759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6760   PetscValidType(mat, 1);
6761   MatCheckPreallocated(mat, 1);
6762   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6763   PetscFunctionReturn(PETSC_SUCCESS);
6764 }
6765 
6766 /*@C
6767    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6768    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6769 
6770    Not Collective, unless matrix has not been allocated
6771 
6772    Input Parameter:
6773 .  mat - the matrix
6774 
6775    Output Parameter:
6776 .  ranges - start of each processors portion plus one more then the total length at the end
6777 
6778    Level: beginner
6779 
6780 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6781 @*/
6782 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6783 {
6784   PetscFunctionBegin;
6785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6786   PetscValidType(mat, 1);
6787   MatCheckPreallocated(mat, 1);
6788   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6789   PetscFunctionReturn(PETSC_SUCCESS);
6790 }
6791 
6792 /*@C
6793    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6794    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6795    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6796 
6797    Not Collective
6798 
6799    Input Parameter:
6800 .  A - matrix
6801 
6802    Output Parameters:
6803 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6804 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6805 
6806    Level: intermediate
6807 
6808 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6809 @*/
6810 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6811 {
6812   PetscErrorCode (*f)(Mat, IS *, IS *);
6813 
6814   PetscFunctionBegin;
6815   MatCheckPreallocated(A, 1);
6816   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6817   if (f) {
6818     PetscCall((*f)(A, rows, cols));
6819   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6820     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6821     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6822   }
6823   PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825 
6826 /*@C
6827    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6828    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6829    to complete the factorization.
6830 
6831    Collective
6832 
6833    Input Parameters:
6834 +  fact - the factorized matrix obtained with `MatGetFactor()`
6835 .  mat - the matrix
6836 .  row - row permutation
6837 .  col - column permutation
6838 -  info - structure containing
6839 .vb
6840       levels - number of levels of fill.
6841       expected fill - as ratio of original fill.
6842       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6843                 missing diagonal entries)
6844 .ve
6845 
6846    Level: developer
6847 
6848    Notes:
6849    See [Matrix Factorization](sec_matfactor) for additional information.
6850 
6851    Most users should employ the `KSP` interface for linear solvers
6852    instead of working directly with matrix algebra routines such as this.
6853    See, e.g., `KSPCreate()`.
6854 
6855    Uses the definition of level of fill as in Y. Saad, 2003
6856 
6857    Developer Note:
6858    The Fortran interface is not autogenerated as the
6859    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6860 
6861    References:
6862 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6863 
6864 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6865           `MatGetOrdering()`, `MatFactorInfo`
6866 @*/
6867 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6868 {
6869   PetscFunctionBegin;
6870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6871   PetscValidType(mat, 2);
6872   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6873   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6874   PetscValidPointer(info, 5);
6875   PetscValidPointer(fact, 1);
6876   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6877   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6878   if (!fact->ops->ilufactorsymbolic) {
6879     MatSolverType stype;
6880     PetscCall(MatFactorGetSolverType(fact, &stype));
6881     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6882   }
6883   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6884   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6885   MatCheckPreallocated(mat, 2);
6886 
6887   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6888   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6889   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6890   PetscFunctionReturn(PETSC_SUCCESS);
6891 }
6892 
6893 /*@C
6894    MatICCFactorSymbolic - Performs symbolic incomplete
6895    Cholesky factorization for a symmetric matrix.  Use
6896    `MatCholeskyFactorNumeric()` to complete the factorization.
6897 
6898    Collective
6899 
6900    Input Parameters:
6901 +  fact - the factorized matrix obtained with `MatGetFactor()`
6902 .  mat - the matrix to be factored
6903 .  perm - row and column permutation
6904 -  info - structure containing
6905 .vb
6906       levels - number of levels of fill.
6907       expected fill - as ratio of original fill.
6908 .ve
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: [](chapter_matrices), `Mat`, `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 - index set of rows to extract
6964 .  icol - index set of columns to extract
6965 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6966 
6967    Output Parameter:
6968 .  submat - the array of submatrices
6969 
6970    Level: advanced
6971 
6972    Notes:
6973    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6974    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6975    to extract a parallel submatrix.
6976 
6977    Some matrix types place restrictions on the row and column
6978    indices, such as that they be sorted or that they be equal to each other.
6979 
6980    The index sets may not have duplicate entries.
6981 
6982    When extracting submatrices from a parallel matrix, each processor can
6983    form a different submatrix by setting the rows and columns of its
6984    individual index sets according to the local submatrix desired.
6985 
6986    When finished using the submatrices, the user should destroy
6987    them with `MatDestroySubMatrices()`.
6988 
6989    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6990    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6991 
6992    This routine creates the matrices in submat; you should NOT create them before
6993    calling it. It also allocates the array of matrix pointers submat.
6994 
6995    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6996    request one row/column in a block, they must request all rows/columns that are in
6997    that block. For example, if the block size is 2 you cannot request just row 0 and
6998    column 0.
6999 
7000    Fortran Note:
7001    The Fortran interface is slightly different from that given below; it
7002    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7003 
7004 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7005 @*/
7006 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7007 {
7008   PetscInt  i;
7009   PetscBool eq;
7010 
7011   PetscFunctionBegin;
7012   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7013   PetscValidType(mat, 1);
7014   if (n) {
7015     PetscValidPointer(irow, 3);
7016     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7017     PetscValidPointer(icol, 4);
7018     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7019   }
7020   PetscValidPointer(submat, 6);
7021   if (n && scall == MAT_REUSE_MATRIX) {
7022     PetscValidPointer(*submat, 6);
7023     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7024   }
7025   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7026   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7027   MatCheckPreallocated(mat, 1);
7028   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7029   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7030   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7031   for (i = 0; i < n; i++) {
7032     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7033     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7034     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7035 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7036     if (mat->boundtocpu && mat->bindingpropagates) {
7037       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7038       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7039     }
7040 #endif
7041   }
7042   PetscFunctionReturn(PETSC_SUCCESS);
7043 }
7044 
7045 /*@C
7046    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7047 
7048    Collective
7049 
7050    Input Parameters:
7051 +  mat - the matrix
7052 .  n   - the number of submatrixes to be extracted
7053 .  irow - index set of rows to extract
7054 .  icol - index set of columns to extract
7055 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7056 
7057    Output Parameter:
7058 .  submat - the array of submatrices
7059 
7060    Level: advanced
7061 
7062    Note:
7063    This is used by `PCGASM`
7064 
7065 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7066 @*/
7067 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7068 {
7069   PetscInt  i;
7070   PetscBool eq;
7071 
7072   PetscFunctionBegin;
7073   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7074   PetscValidType(mat, 1);
7075   if (n) {
7076     PetscValidPointer(irow, 3);
7077     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7078     PetscValidPointer(icol, 4);
7079     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7080   }
7081   PetscValidPointer(submat, 6);
7082   if (n && scall == MAT_REUSE_MATRIX) {
7083     PetscValidPointer(*submat, 6);
7084     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7085   }
7086   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7087   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7088   MatCheckPreallocated(mat, 1);
7089 
7090   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7091   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7092   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7093   for (i = 0; i < n; i++) {
7094     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7095     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7096   }
7097   PetscFunctionReturn(PETSC_SUCCESS);
7098 }
7099 
7100 /*@C
7101    MatDestroyMatrices - Destroys an array of matrices.
7102 
7103    Collective
7104 
7105    Input Parameters:
7106 +  n - the number of local matrices
7107 -  mat - the matrices (this is a pointer to the array of matrices)
7108 
7109    Level: advanced
7110 
7111     Note:
7112     Frees not only the matrices, but also the array that contains the matrices
7113 
7114     Fortran Note:
7115     This does not free the array.
7116 
7117 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7118 @*/
7119 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7120 {
7121   PetscInt i;
7122 
7123   PetscFunctionBegin;
7124   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7125   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7126   PetscValidPointer(mat, 2);
7127 
7128   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7129 
7130   /* memory is allocated even if n = 0 */
7131   PetscCall(PetscFree(*mat));
7132   PetscFunctionReturn(PETSC_SUCCESS);
7133 }
7134 
7135 /*@C
7136    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7137 
7138    Collective
7139 
7140    Input Parameters:
7141 +  n - the number of local matrices
7142 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7143                        sequence of `MatCreateSubMatrices()`)
7144 
7145    Level: advanced
7146 
7147     Note:
7148     Frees not only the matrices, but also the array that contains the matrices
7149 
7150     Fortran Note:
7151     This does not free the array.
7152 
7153 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7154 @*/
7155 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7156 {
7157   Mat mat0;
7158 
7159   PetscFunctionBegin;
7160   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7161   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7162   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7163   PetscValidPointer(mat, 2);
7164 
7165   mat0 = (*mat)[0];
7166   if (mat0 && mat0->ops->destroysubmatrices) {
7167     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7168   } else {
7169     PetscCall(MatDestroyMatrices(n, mat));
7170   }
7171   PetscFunctionReturn(PETSC_SUCCESS);
7172 }
7173 
7174 /*@C
7175    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7176 
7177    Collective
7178 
7179    Input Parameter:
7180 .  mat - the matrix
7181 
7182    Output Parameter:
7183 .  matstruct - the sequential matrix with the nonzero structure of mat
7184 
7185   Level: developer
7186 
7187 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7188 @*/
7189 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7190 {
7191   PetscFunctionBegin;
7192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7193   PetscValidPointer(matstruct, 2);
7194 
7195   PetscValidType(mat, 1);
7196   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7197   MatCheckPreallocated(mat, 1);
7198 
7199   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7200   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7201   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7202   PetscFunctionReturn(PETSC_SUCCESS);
7203 }
7204 
7205 /*@C
7206    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7207 
7208    Collective
7209 
7210    Input Parameter:
7211 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7212                        sequence of `MatGetSequentialNonzeroStructure()`)
7213 
7214    Level: advanced
7215 
7216     Note:
7217     Frees not only the matrices, but also the array that contains the matrices
7218 
7219 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7220 @*/
7221 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7222 {
7223   PetscFunctionBegin;
7224   PetscValidPointer(mat, 1);
7225   PetscCall(MatDestroy(mat));
7226   PetscFunctionReturn(PETSC_SUCCESS);
7227 }
7228 
7229 /*@
7230    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7231    replaces the index sets by larger ones that represent submatrices with
7232    additional overlap.
7233 
7234    Collective
7235 
7236    Input Parameters:
7237 +  mat - the matrix
7238 .  n   - the number of index sets
7239 .  is  - the array of index sets (these index sets will changed during the call)
7240 -  ov  - the additional overlap requested
7241 
7242    Options Database Key:
7243 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7244 
7245    Level: developer
7246 
7247    Note:
7248    The computed overlap preserves the matrix block sizes when the blocks are square.
7249    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7250    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7251 
7252 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7253 @*/
7254 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7255 {
7256   PetscInt i, bs, cbs;
7257 
7258   PetscFunctionBegin;
7259   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7260   PetscValidType(mat, 1);
7261   PetscValidLogicalCollectiveInt(mat, n, 2);
7262   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7263   if (n) {
7264     PetscValidPointer(is, 3);
7265     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7266   }
7267   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7268   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7269   MatCheckPreallocated(mat, 1);
7270 
7271   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7272   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7273   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7274   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7275   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7276   if (bs == cbs) {
7277     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7278   }
7279   PetscFunctionReturn(PETSC_SUCCESS);
7280 }
7281 
7282 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7283 
7284 /*@
7285    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7286    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7287    additional overlap.
7288 
7289    Collective
7290 
7291    Input Parameters:
7292 +  mat - the matrix
7293 .  n   - the number of index sets
7294 .  is  - the array of index sets (these index sets will changed during the call)
7295 -  ov  - the additional overlap requested
7296 
7297 `   Options Database Key:
7298 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7299 
7300    Level: developer
7301 
7302 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7303 @*/
7304 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7305 {
7306   PetscInt i;
7307 
7308   PetscFunctionBegin;
7309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7310   PetscValidType(mat, 1);
7311   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7312   if (n) {
7313     PetscValidPointer(is, 3);
7314     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7315   }
7316   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7317   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7318   MatCheckPreallocated(mat, 1);
7319   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7320   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7321   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7322   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7323   PetscFunctionReturn(PETSC_SUCCESS);
7324 }
7325 
7326 /*@
7327    MatGetBlockSize - Returns the matrix block size.
7328 
7329    Not Collective
7330 
7331    Input Parameter:
7332 .  mat - the matrix
7333 
7334    Output Parameter:
7335 .  bs - block size
7336 
7337    Level: intermediate
7338 
7339    Notes:
7340     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7341 
7342    If the block size has not been set yet this routine returns 1.
7343 
7344 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7345 @*/
7346 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7347 {
7348   PetscFunctionBegin;
7349   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7350   PetscValidIntPointer(bs, 2);
7351   *bs = PetscAbs(mat->rmap->bs);
7352   PetscFunctionReturn(PETSC_SUCCESS);
7353 }
7354 
7355 /*@
7356    MatGetBlockSizes - Returns the matrix block row and column sizes.
7357 
7358    Not Collective
7359 
7360    Input Parameter:
7361 .  mat - the matrix
7362 
7363    Output Parameters:
7364 +  rbs - row block size
7365 -  cbs - column block size
7366 
7367    Level: intermediate
7368 
7369    Notes:
7370     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7371     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7372 
7373    If a block size has not been set yet this routine returns 1.
7374 
7375 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7376 @*/
7377 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7378 {
7379   PetscFunctionBegin;
7380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7381   if (rbs) PetscValidIntPointer(rbs, 2);
7382   if (cbs) PetscValidIntPointer(cbs, 3);
7383   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7384   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7385   PetscFunctionReturn(PETSC_SUCCESS);
7386 }
7387 
7388 /*@
7389    MatSetBlockSize - Sets the matrix block size.
7390 
7391    Logically Collective
7392 
7393    Input Parameters:
7394 +  mat - the matrix
7395 -  bs - block size
7396 
7397    Level: intermediate
7398 
7399    Notes:
7400     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7401     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7402 
7403     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7404     is compatible with the matrix local sizes.
7405 
7406 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7407 @*/
7408 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7409 {
7410   PetscFunctionBegin;
7411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7412   PetscValidLogicalCollectiveInt(mat, bs, 2);
7413   PetscCall(MatSetBlockSizes(mat, bs, bs));
7414   PetscFunctionReturn(PETSC_SUCCESS);
7415 }
7416 
7417 typedef struct {
7418   PetscInt         n;
7419   IS              *is;
7420   Mat             *mat;
7421   PetscObjectState nonzerostate;
7422   Mat              C;
7423 } EnvelopeData;
7424 
7425 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7426 {
7427   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7428   PetscCall(PetscFree(edata->is));
7429   PetscCall(PetscFree(edata));
7430   return PETSC_SUCCESS;
7431 }
7432 
7433 /*
7434    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7435          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7436 
7437    Collective
7438 
7439    Input Parameter:
7440 .  mat - the matrix
7441 
7442    Notes:
7443      There can be zeros within the blocks
7444 
7445      The blocks can overlap between processes, including laying on more than two processes
7446 
7447 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7448 */
7449 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7450 {
7451   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7452   PetscInt          *diag, *odiag, sc;
7453   VecScatter         scatter;
7454   PetscScalar       *seqv;
7455   const PetscScalar *parv;
7456   const PetscInt    *ia, *ja;
7457   PetscBool          set, flag, done;
7458   Mat                AA = mat, A;
7459   MPI_Comm           comm;
7460   PetscMPIInt        rank, size, tag;
7461   MPI_Status         status;
7462   PetscContainer     container;
7463   EnvelopeData      *edata;
7464   Vec                seq, par;
7465   IS                 isglobal;
7466 
7467   PetscFunctionBegin;
7468   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7469   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7470   if (!set || !flag) {
7471     /* TOO: only needs nonzero structure of transpose */
7472     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7473     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7474   }
7475   PetscCall(MatAIJGetLocalMat(AA, &A));
7476   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7477   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7478 
7479   PetscCall(MatGetLocalSize(mat, &n, NULL));
7480   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7481   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7482   PetscCallMPI(MPI_Comm_size(comm, &size));
7483   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7484 
7485   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7486 
7487   if (rank > 0) {
7488     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7489     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7490   }
7491   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7492   for (i = 0; i < n; i++) {
7493     env = PetscMax(env, ja[ia[i + 1] - 1]);
7494     II  = rstart + i;
7495     if (env == II) {
7496       starts[lblocks]  = tbs;
7497       sizes[lblocks++] = 1 + II - tbs;
7498       tbs              = 1 + II;
7499     }
7500   }
7501   if (rank < size - 1) {
7502     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7503     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7504   }
7505 
7506   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7507   if (!set || !flag) PetscCall(MatDestroy(&AA));
7508   PetscCall(MatDestroy(&A));
7509 
7510   PetscCall(PetscNew(&edata));
7511   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7512   edata->n = lblocks;
7513   /* create IS needed for extracting blocks from the original matrix */
7514   PetscCall(PetscMalloc1(lblocks, &edata->is));
7515   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7516 
7517   /* Create the resulting inverse matrix structure with preallocation information */
7518   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7519   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7520   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7521   PetscCall(MatSetType(edata->C, MATAIJ));
7522 
7523   /* Communicate the start and end of each row, from each block to the correct rank */
7524   /* TODO: Use PetscSF instead of VecScatter */
7525   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7526   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7527   PetscCall(VecGetArrayWrite(seq, &seqv));
7528   for (PetscInt i = 0; i < lblocks; i++) {
7529     for (PetscInt j = 0; j < sizes[i]; j++) {
7530       seqv[cnt]     = starts[i];
7531       seqv[cnt + 1] = starts[i] + sizes[i];
7532       cnt += 2;
7533     }
7534   }
7535   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7536   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7537   sc -= cnt;
7538   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7539   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7540   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7541   PetscCall(ISDestroy(&isglobal));
7542   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7543   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7544   PetscCall(VecScatterDestroy(&scatter));
7545   PetscCall(VecDestroy(&seq));
7546   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7547   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7548   PetscCall(VecGetArrayRead(par, &parv));
7549   cnt = 0;
7550   PetscCall(MatGetSize(mat, NULL, &n));
7551   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7552     PetscInt start, end, d = 0, od = 0;
7553 
7554     start = (PetscInt)PetscRealPart(parv[cnt]);
7555     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7556     cnt += 2;
7557 
7558     if (start < cstart) {
7559       od += cstart - start + n - cend;
7560       d += cend - cstart;
7561     } else if (start < cend) {
7562       od += n - cend;
7563       d += cend - start;
7564     } else od += n - start;
7565     if (end <= cstart) {
7566       od -= cstart - end + n - cend;
7567       d -= cend - cstart;
7568     } else if (end < cend) {
7569       od -= n - cend;
7570       d -= cend - end;
7571     } else od -= n - end;
7572 
7573     odiag[i] = od;
7574     diag[i]  = d;
7575   }
7576   PetscCall(VecRestoreArrayRead(par, &parv));
7577   PetscCall(VecDestroy(&par));
7578   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7579   PetscCall(PetscFree2(diag, odiag));
7580   PetscCall(PetscFree2(sizes, starts));
7581 
7582   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7583   PetscCall(PetscContainerSetPointer(container, edata));
7584   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7585   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7586   PetscCall(PetscObjectDereference((PetscObject)container));
7587   PetscFunctionReturn(PETSC_SUCCESS);
7588 }
7589 
7590 /*@
7591   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7592 
7593   Collective
7594 
7595   Input Parameters:
7596 + A - the matrix
7597 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7598 
7599   Output Parameter:
7600 . C - matrix with inverted block diagonal of `A`
7601 
7602   Level: advanced
7603 
7604   Note:
7605      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7606 
7607 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7608 @*/
7609 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7610 {
7611   PetscContainer   container;
7612   EnvelopeData    *edata;
7613   PetscObjectState nonzerostate;
7614 
7615   PetscFunctionBegin;
7616   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7617   if (!container) {
7618     PetscCall(MatComputeVariableBlockEnvelope(A));
7619     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7620   }
7621   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7622   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7623   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7624   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7625 
7626   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7627   *C = edata->C;
7628 
7629   for (PetscInt i = 0; i < edata->n; i++) {
7630     Mat          D;
7631     PetscScalar *dvalues;
7632 
7633     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7634     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7635     PetscCall(MatSeqDenseInvert(D));
7636     PetscCall(MatDenseGetArray(D, &dvalues));
7637     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7638     PetscCall(MatDestroy(&D));
7639   }
7640   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7641   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7642   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7643   PetscFunctionReturn(PETSC_SUCCESS);
7644 }
7645 
7646 /*@
7647    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7648 
7649    Logically Collective
7650 
7651    Input Parameters:
7652 +  mat - the matrix
7653 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7654 -  bsizes - the block sizes
7655 
7656    Level: intermediate
7657 
7658    Notes:
7659     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7660 
7661     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.
7662 
7663 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7664           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7665 @*/
7666 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7667 {
7668   PetscInt i, ncnt = 0, nlocal;
7669 
7670   PetscFunctionBegin;
7671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7672   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7673   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7674   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7675   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);
7676   PetscCall(PetscFree(mat->bsizes));
7677   mat->nblocks = nblocks;
7678   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7679   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7680   PetscFunctionReturn(PETSC_SUCCESS);
7681 }
7682 
7683 /*@C
7684    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7685 
7686    Logically Collective; No Fortran Support
7687 
7688    Input Parameter:
7689 .  mat - the matrix
7690 
7691    Output Parameters:
7692 +  nblocks - the number of blocks on this process
7693 -  bsizes - the block sizes
7694 
7695    Level: intermediate
7696 
7697 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7698 @*/
7699 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7700 {
7701   PetscFunctionBegin;
7702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7703   *nblocks = mat->nblocks;
7704   *bsizes  = mat->bsizes;
7705   PetscFunctionReturn(PETSC_SUCCESS);
7706 }
7707 
7708 /*@
7709    MatSetBlockSizes - Sets the matrix block row and column sizes.
7710 
7711    Logically Collective
7712 
7713    Input Parameters:
7714 +  mat - the matrix
7715 .  rbs - row block size
7716 -  cbs - column block size
7717 
7718    Level: intermediate
7719 
7720    Notes:
7721     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7722     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7723     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7724 
7725     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7726     are compatible with the matrix local sizes.
7727 
7728     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7729 
7730 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7731 @*/
7732 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7733 {
7734   PetscFunctionBegin;
7735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7736   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7737   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7738   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7739   if (mat->rmap->refcnt) {
7740     ISLocalToGlobalMapping l2g  = NULL;
7741     PetscLayout            nmap = NULL;
7742 
7743     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7744     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7745     PetscCall(PetscLayoutDestroy(&mat->rmap));
7746     mat->rmap          = nmap;
7747     mat->rmap->mapping = l2g;
7748   }
7749   if (mat->cmap->refcnt) {
7750     ISLocalToGlobalMapping l2g  = NULL;
7751     PetscLayout            nmap = NULL;
7752 
7753     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7754     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7755     PetscCall(PetscLayoutDestroy(&mat->cmap));
7756     mat->cmap          = nmap;
7757     mat->cmap->mapping = l2g;
7758   }
7759   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7760   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7761   PetscFunctionReturn(PETSC_SUCCESS);
7762 }
7763 
7764 /*@
7765    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7766 
7767    Logically Collective
7768 
7769    Input Parameters:
7770 +  mat - the matrix
7771 .  fromRow - matrix from which to copy row block size
7772 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7773 
7774    Level: developer
7775 
7776 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7777 @*/
7778 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7779 {
7780   PetscFunctionBegin;
7781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7782   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7783   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7784   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7785   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7786   PetscFunctionReturn(PETSC_SUCCESS);
7787 }
7788 
7789 /*@
7790    MatResidual - Default routine to calculate the residual r = b - Ax
7791 
7792    Collective
7793 
7794    Input Parameters:
7795 +  mat - the matrix
7796 .  b   - the right-hand-side
7797 -  x   - the approximate solution
7798 
7799    Output Parameter:
7800 .  r - location to store the residual
7801 
7802    Level: developer
7803 
7804 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7805 @*/
7806 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7807 {
7808   PetscFunctionBegin;
7809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7810   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7811   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7812   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7813   PetscValidType(mat, 1);
7814   MatCheckPreallocated(mat, 1);
7815   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7816   if (!mat->ops->residual) {
7817     PetscCall(MatMult(mat, x, r));
7818     PetscCall(VecAYPX(r, -1.0, b));
7819   } else {
7820     PetscUseTypeMethod(mat, residual, b, x, r);
7821   }
7822   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7823   PetscFunctionReturn(PETSC_SUCCESS);
7824 }
7825 
7826 /*MC
7827     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7828 
7829     Synopsis:
7830     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7831 
7832     Not Collective
7833 
7834     Input Parameters:
7835 +   A - the matrix
7836 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7837 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7838 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7839                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7840                  always used.
7841 
7842     Output Parameters:
7843 +   n - number of local rows in the (possibly compressed) matrix
7844 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7845 .   ja - the column indices
7846 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7847            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7848 
7849     Level: developer
7850 
7851     Note:
7852     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7853 
7854 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7855 M*/
7856 
7857 /*MC
7858     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7859 
7860     Synopsis:
7861     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7862 
7863     Not Collective
7864 
7865     Input Parameters:
7866 +   A - the  matrix
7867 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7868 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7869     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7870                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7871                  always used.
7872 .   n - number of local rows in the (possibly compressed) matrix
7873 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7874 .   ja - the column indices
7875 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7876            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7877 
7878     Level: developer
7879 
7880 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7881 M*/
7882 
7883 /*@C
7884     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7885 
7886    Collective
7887 
7888     Input Parameters:
7889 +   mat - the matrix
7890 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7891 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7892 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7893                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7894                  always used.
7895 
7896     Output Parameters:
7897 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7898 .   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
7899 .   ja - the column indices, use `NULL` if not needed
7900 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7901            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7902 
7903     Level: developer
7904 
7905     Notes:
7906     You CANNOT change any of the ia[] or ja[] values.
7907 
7908     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7909 
7910     Fortran Notes:
7911     Use
7912 .vb
7913     PetscInt, pointer :: ia(:),ja(:)
7914     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7915     ! Access the ith and jth entries via ia(i) and ja(j)
7916 .ve
7917    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7918 
7919 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7920 @*/
7921 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7922 {
7923   PetscFunctionBegin;
7924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7925   PetscValidType(mat, 1);
7926   if (n) PetscValidIntPointer(n, 5);
7927   if (ia) PetscValidPointer(ia, 6);
7928   if (ja) PetscValidPointer(ja, 7);
7929   if (done) PetscValidBoolPointer(done, 8);
7930   MatCheckPreallocated(mat, 1);
7931   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7932   else {
7933     if (done) *done = PETSC_TRUE;
7934     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7935     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7936     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7937   }
7938   PetscFunctionReturn(PETSC_SUCCESS);
7939 }
7940 
7941 /*@C
7942     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7943 
7944     Collective
7945 
7946     Input Parameters:
7947 +   mat - the matrix
7948 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7949 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7950                 symmetrized
7951 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7952                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7953                  always used.
7954 .   n - number of columns in the (possibly compressed) matrix
7955 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7956 -   ja - the row indices
7957 
7958     Output Parameter:
7959 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7960 
7961     Level: developer
7962 
7963 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7964 @*/
7965 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7966 {
7967   PetscFunctionBegin;
7968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7969   PetscValidType(mat, 1);
7970   PetscValidIntPointer(n, 5);
7971   if (ia) PetscValidPointer(ia, 6);
7972   if (ja) PetscValidPointer(ja, 7);
7973   PetscValidBoolPointer(done, 8);
7974   MatCheckPreallocated(mat, 1);
7975   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7976   else {
7977     *done = PETSC_TRUE;
7978     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7979   }
7980   PetscFunctionReturn(PETSC_SUCCESS);
7981 }
7982 
7983 /*@C
7984     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7985 
7986     Collective
7987 
7988     Input Parameters:
7989 +   mat - the matrix
7990 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7991 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7992 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7993                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7994                  always used.
7995 .   n - size of (possibly compressed) matrix
7996 .   ia - the row pointers
7997 -   ja - the column indices
7998 
7999     Output Parameter:
8000 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8001 
8002     Level: developer
8003 
8004     Note:
8005     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8006     us of the array after it has been restored. If you pass `NULL`, it will
8007     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8008 
8009     Fortran Note:
8010    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8011 
8012 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8013 @*/
8014 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8015 {
8016   PetscFunctionBegin;
8017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8018   PetscValidType(mat, 1);
8019   if (ia) PetscValidPointer(ia, 6);
8020   if (ja) PetscValidPointer(ja, 7);
8021   if (done) PetscValidBoolPointer(done, 8);
8022   MatCheckPreallocated(mat, 1);
8023 
8024   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8025   else {
8026     if (done) *done = PETSC_TRUE;
8027     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8028     if (n) *n = 0;
8029     if (ia) *ia = NULL;
8030     if (ja) *ja = NULL;
8031   }
8032   PetscFunctionReturn(PETSC_SUCCESS);
8033 }
8034 
8035 /*@C
8036     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8037 
8038     Collective
8039 
8040     Input Parameters:
8041 +   mat - the matrix
8042 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8043 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8044 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8045                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8046                  always used.
8047 
8048     Output Parameters:
8049 +   n - size of (possibly compressed) matrix
8050 .   ia - the column pointers
8051 .   ja - the row indices
8052 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8053 
8054     Level: developer
8055 
8056 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8057 @*/
8058 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8059 {
8060   PetscFunctionBegin;
8061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8062   PetscValidType(mat, 1);
8063   if (ia) PetscValidPointer(ia, 6);
8064   if (ja) PetscValidPointer(ja, 7);
8065   PetscValidBoolPointer(done, 8);
8066   MatCheckPreallocated(mat, 1);
8067 
8068   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8069   else {
8070     *done = PETSC_TRUE;
8071     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8072     if (n) *n = 0;
8073     if (ia) *ia = NULL;
8074     if (ja) *ja = NULL;
8075   }
8076   PetscFunctionReturn(PETSC_SUCCESS);
8077 }
8078 
8079 /*@C
8080     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8081 
8082     Collective
8083 
8084     Input Parameters:
8085 +   mat - the matrix
8086 .   ncolors - maximum color value
8087 .   n   - number of entries in colorarray
8088 -   colorarray - array indicating color for each column
8089 
8090     Output Parameter:
8091 .   iscoloring - coloring generated using colorarray information
8092 
8093     Level: developer
8094 
8095 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8096 @*/
8097 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8098 {
8099   PetscFunctionBegin;
8100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8101   PetscValidType(mat, 1);
8102   PetscValidIntPointer(colorarray, 4);
8103   PetscValidPointer(iscoloring, 5);
8104   MatCheckPreallocated(mat, 1);
8105 
8106   if (!mat->ops->coloringpatch) {
8107     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8108   } else {
8109     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8110   }
8111   PetscFunctionReturn(PETSC_SUCCESS);
8112 }
8113 
8114 /*@
8115    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8116 
8117    Logically Collective
8118 
8119    Input Parameter:
8120 .  mat - the factored matrix to be reset
8121 
8122    Level: developer
8123 
8124    Notes:
8125    This routine should be used only with factored matrices formed by in-place
8126    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8127    format).  This option can save memory, for example, when solving nonlinear
8128    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8129    ILU(0) preconditioner.
8130 
8131    One can specify in-place ILU(0) factorization by calling
8132 .vb
8133      PCType(pc,PCILU);
8134      PCFactorSeUseInPlace(pc);
8135 .ve
8136    or by using the options -pc_type ilu -pc_factor_in_place
8137 
8138    In-place factorization ILU(0) can also be used as a local
8139    solver for the blocks within the block Jacobi or additive Schwarz
8140    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8141    for details on setting local solver options.
8142 
8143    Most users should employ the `KSP` interface for linear solvers
8144    instead of working directly with matrix algebra routines such as this.
8145    See, e.g., `KSPCreate()`.
8146 
8147 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8148 @*/
8149 PetscErrorCode MatSetUnfactored(Mat mat)
8150 {
8151   PetscFunctionBegin;
8152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8153   PetscValidType(mat, 1);
8154   MatCheckPreallocated(mat, 1);
8155   mat->factortype = MAT_FACTOR_NONE;
8156   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8157   PetscUseTypeMethod(mat, setunfactored);
8158   PetscFunctionReturn(PETSC_SUCCESS);
8159 }
8160 
8161 /*MC
8162     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8163 
8164     Synopsis:
8165     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8166 
8167     Not Collective
8168 
8169     Input Parameter:
8170 .   x - matrix
8171 
8172     Output Parameters:
8173 +   xx_v - the Fortran pointer to the array
8174 -   ierr - error code
8175 
8176     Example of Usage:
8177 .vb
8178       PetscScalar, pointer xx_v(:,:)
8179       ....
8180       call MatDenseGetArrayF90(x,xx_v,ierr)
8181       a = xx_v(3)
8182       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8183 .ve
8184 
8185     Level: advanced
8186 
8187 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8188 M*/
8189 
8190 /*MC
8191     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8192     accessed with `MatDenseGetArrayF90()`.
8193 
8194     Synopsis:
8195     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8196 
8197     Not Collective
8198 
8199     Input Parameters:
8200 +   x - matrix
8201 -   xx_v - the Fortran90 pointer to the array
8202 
8203     Output Parameter:
8204 .   ierr - error code
8205 
8206     Example of Usage:
8207 .vb
8208        PetscScalar, pointer xx_v(:,:)
8209        ....
8210        call MatDenseGetArrayF90(x,xx_v,ierr)
8211        a = xx_v(3)
8212        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8213 .ve
8214 
8215     Level: advanced
8216 
8217 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8218 M*/
8219 
8220 /*MC
8221     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8222 
8223     Synopsis:
8224     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8225 
8226     Not Collective
8227 
8228     Input Parameter:
8229 .   x - matrix
8230 
8231     Output Parameters:
8232 +   xx_v - the Fortran pointer to the array
8233 -   ierr - error code
8234 
8235     Example of Usage:
8236 .vb
8237       PetscScalar, pointer xx_v(:)
8238       ....
8239       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8240       a = xx_v(3)
8241       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8242 .ve
8243 
8244     Level: advanced
8245 
8246 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8247 M*/
8248 
8249 /*MC
8250     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8251     accessed with `MatSeqAIJGetArrayF90()`.
8252 
8253     Synopsis:
8254     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8255 
8256     Not Collective
8257 
8258     Input Parameters:
8259 +   x - matrix
8260 -   xx_v - the Fortran90 pointer to the array
8261 
8262     Output Parameter:
8263 .   ierr - error code
8264 
8265     Example of Usage:
8266 .vb
8267        PetscScalar, pointer xx_v(:)
8268        ....
8269        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8270        a = xx_v(3)
8271        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8272 .ve
8273 
8274     Level: advanced
8275 
8276 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8277 M*/
8278 
8279 /*@
8280     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8281                       as the original matrix.
8282 
8283     Collective
8284 
8285     Input Parameters:
8286 +   mat - the original matrix
8287 .   isrow - parallel `IS` containing the rows this processor should obtain
8288 .   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.
8289 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8290 
8291     Output Parameter:
8292 .   newmat - the new submatrix, of the same type as the original matrix
8293 
8294     Level: advanced
8295 
8296     Notes:
8297     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8298 
8299     Some matrix types place restrictions on the row and column indices, such
8300     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;
8301     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8302 
8303     The index sets may not have duplicate entries.
8304 
8305       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8306    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8307    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8308    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8309    you are finished using it.
8310 
8311     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8312     the input matrix.
8313 
8314     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8315 
8316    Example usage:
8317    Consider the following 8x8 matrix with 34 non-zero values, that is
8318    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8319    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8320    as follows
8321 .vb
8322             1  2  0  |  0  3  0  |  0  4
8323     Proc0   0  5  6  |  7  0  0  |  8  0
8324             9  0 10  | 11  0  0  | 12  0
8325     -------------------------------------
8326            13  0 14  | 15 16 17  |  0  0
8327     Proc1   0 18  0  | 19 20 21  |  0  0
8328             0  0  0  | 22 23  0  | 24  0
8329     -------------------------------------
8330     Proc2  25 26 27  |  0  0 28  | 29  0
8331            30  0  0  | 31 32 33  |  0 34
8332 .ve
8333 
8334     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8335 
8336 .vb
8337             2  0  |  0  3  0  |  0
8338     Proc0   5  6  |  7  0  0  |  8
8339     -------------------------------
8340     Proc1  18  0  | 19 20 21  |  0
8341     -------------------------------
8342     Proc2  26 27  |  0  0 28  | 29
8343             0  0  | 31 32 33  |  0
8344 .ve
8345 
8346 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8347 @*/
8348 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8349 {
8350   PetscMPIInt size;
8351   Mat        *local;
8352   IS          iscoltmp;
8353   PetscBool   flg;
8354 
8355   PetscFunctionBegin;
8356   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8357   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8358   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8359   PetscValidPointer(newmat, 5);
8360   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8361   PetscValidType(mat, 1);
8362   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8363   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8364 
8365   MatCheckPreallocated(mat, 1);
8366   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8367 
8368   if (!iscol || isrow == iscol) {
8369     PetscBool   stride;
8370     PetscMPIInt grabentirematrix = 0, grab;
8371     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8372     if (stride) {
8373       PetscInt first, step, n, rstart, rend;
8374       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8375       if (step == 1) {
8376         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8377         if (rstart == first) {
8378           PetscCall(ISGetLocalSize(isrow, &n));
8379           if (n == rend - rstart) grabentirematrix = 1;
8380         }
8381       }
8382     }
8383     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8384     if (grab) {
8385       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8386       if (cll == MAT_INITIAL_MATRIX) {
8387         *newmat = mat;
8388         PetscCall(PetscObjectReference((PetscObject)mat));
8389       }
8390       PetscFunctionReturn(PETSC_SUCCESS);
8391     }
8392   }
8393 
8394   if (!iscol) {
8395     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8396   } else {
8397     iscoltmp = iscol;
8398   }
8399 
8400   /* if original matrix is on just one processor then use submatrix generated */
8401   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8402     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8403     goto setproperties;
8404   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8405     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8406     *newmat = *local;
8407     PetscCall(PetscFree(local));
8408     goto setproperties;
8409   } else if (!mat->ops->createsubmatrix) {
8410     /* Create a new matrix type that implements the operation using the full matrix */
8411     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8412     switch (cll) {
8413     case MAT_INITIAL_MATRIX:
8414       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8415       break;
8416     case MAT_REUSE_MATRIX:
8417       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8418       break;
8419     default:
8420       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8421     }
8422     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8423     goto setproperties;
8424   }
8425 
8426   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8427   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8428   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8429 
8430 setproperties:
8431   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8432   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8433   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8434   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8435   PetscFunctionReturn(PETSC_SUCCESS);
8436 }
8437 
8438 /*@
8439    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8440 
8441    Not Collective
8442 
8443    Input Parameters:
8444 +  A - the matrix we wish to propagate options from
8445 -  B - the matrix we wish to propagate options to
8446 
8447    Level: beginner
8448 
8449    Note:
8450    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8451 
8452 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8453 @*/
8454 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8455 {
8456   PetscFunctionBegin;
8457   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8458   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8459   B->symmetry_eternal            = A->symmetry_eternal;
8460   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8461   B->symmetric                   = A->symmetric;
8462   B->structurally_symmetric      = A->structurally_symmetric;
8463   B->spd                         = A->spd;
8464   B->hermitian                   = A->hermitian;
8465   PetscFunctionReturn(PETSC_SUCCESS);
8466 }
8467 
8468 /*@
8469    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8470    used during the assembly process to store values that belong to
8471    other processors.
8472 
8473    Not Collective
8474 
8475    Input Parameters:
8476 +  mat   - the matrix
8477 .  size  - the initial size of the stash.
8478 -  bsize - the initial size of the block-stash(if used).
8479 
8480    Options Database Keys:
8481 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8482 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8483 
8484    Level: intermediate
8485 
8486    Notes:
8487      The block-stash is used for values set with `MatSetValuesBlocked()` while
8488      the stash is used for values set with `MatSetValues()`
8489 
8490      Run with the option -info and look for output of the form
8491      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8492      to determine the appropriate value, MM, to use for size and
8493      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8494      to determine the value, BMM to use for bsize
8495 
8496 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8497 @*/
8498 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8499 {
8500   PetscFunctionBegin;
8501   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8502   PetscValidType(mat, 1);
8503   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8504   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8505   PetscFunctionReturn(PETSC_SUCCESS);
8506 }
8507 
8508 /*@
8509    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8510      the matrix
8511 
8512    Neighbor-wise Collective
8513 
8514    Input Parameters:
8515 +  mat   - the matrix
8516 .  x - the vector to be multiplied by the interpolation operator
8517 -  y - the vector to be added to the result
8518 
8519    Output Parameter:
8520 .  w - the resulting vector
8521 
8522    Level: intermediate
8523 
8524    Notes:
8525     `w` may be the same vector as `y`.
8526 
8527     This allows one to use either the restriction or interpolation (its transpose)
8528     matrix to do the interpolation
8529 
8530 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8531 @*/
8532 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8533 {
8534   PetscInt M, N, Ny;
8535 
8536   PetscFunctionBegin;
8537   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8538   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8539   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8540   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8541   PetscCall(MatGetSize(A, &M, &N));
8542   PetscCall(VecGetSize(y, &Ny));
8543   if (M == Ny) {
8544     PetscCall(MatMultAdd(A, x, y, w));
8545   } else {
8546     PetscCall(MatMultTransposeAdd(A, x, y, w));
8547   }
8548   PetscFunctionReturn(PETSC_SUCCESS);
8549 }
8550 
8551 /*@
8552    MatInterpolate - y = A*x or A'*x depending on the shape of
8553      the matrix
8554 
8555    Neighbor-wise Collective
8556 
8557    Input Parameters:
8558 +  mat   - the matrix
8559 -  x - the vector to be interpolated
8560 
8561    Output Parameter:
8562 .  y - the resulting vector
8563 
8564    Level: intermediate
8565 
8566    Note:
8567     This allows one to use either the restriction or interpolation (its transpose)
8568     matrix to do the interpolation
8569 
8570 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8571 @*/
8572 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8573 {
8574   PetscInt M, N, Ny;
8575 
8576   PetscFunctionBegin;
8577   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8578   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8579   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8580   PetscCall(MatGetSize(A, &M, &N));
8581   PetscCall(VecGetSize(y, &Ny));
8582   if (M == Ny) {
8583     PetscCall(MatMult(A, x, y));
8584   } else {
8585     PetscCall(MatMultTranspose(A, x, y));
8586   }
8587   PetscFunctionReturn(PETSC_SUCCESS);
8588 }
8589 
8590 /*@
8591    MatRestrict - y = A*x or A'*x
8592 
8593    Neighbor-wise Collective
8594 
8595    Input Parameters:
8596 +  mat   - the matrix
8597 -  x - the vector to be restricted
8598 
8599    Output Parameter:
8600 .  y - the resulting vector
8601 
8602    Level: intermediate
8603 
8604    Note:
8605     This allows one to use either the restriction or interpolation (its transpose)
8606     matrix to do the restriction
8607 
8608 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8609 @*/
8610 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8611 {
8612   PetscInt M, N, Ny;
8613 
8614   PetscFunctionBegin;
8615   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8616   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8617   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8618   PetscCall(MatGetSize(A, &M, &N));
8619   PetscCall(VecGetSize(y, &Ny));
8620   if (M == Ny) {
8621     PetscCall(MatMult(A, x, y));
8622   } else {
8623     PetscCall(MatMultTranspose(A, x, y));
8624   }
8625   PetscFunctionReturn(PETSC_SUCCESS);
8626 }
8627 
8628 /*@
8629    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8630 
8631    Neighbor-wise Collective
8632 
8633    Input Parameters:
8634 +  mat   - the matrix
8635 .  x - the input dense matrix to be multiplied
8636 -  w - the input dense matrix to be added to the result
8637 
8638    Output Parameter:
8639 .  y - the output dense matrix
8640 
8641    Level: intermediate
8642 
8643    Note:
8644     This allows one to use either the restriction or interpolation (its transpose)
8645     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8646     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8647 
8648 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8649 @*/
8650 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8651 {
8652   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8653   PetscBool trans = PETSC_TRUE;
8654   MatReuse  reuse = MAT_INITIAL_MATRIX;
8655 
8656   PetscFunctionBegin;
8657   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8658   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8659   PetscValidType(x, 2);
8660   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8661   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8662   PetscCall(MatGetSize(A, &M, &N));
8663   PetscCall(MatGetSize(x, &Mx, &Nx));
8664   if (N == Mx) trans = PETSC_FALSE;
8665   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);
8666   Mo = trans ? N : M;
8667   if (*y) {
8668     PetscCall(MatGetSize(*y, &My, &Ny));
8669     if (Mo == My && Nx == Ny) {
8670       reuse = MAT_REUSE_MATRIX;
8671     } else {
8672       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);
8673       PetscCall(MatDestroy(y));
8674     }
8675   }
8676 
8677   if (w && *y == w) { /* this is to minimize changes in PCMG */
8678     PetscBool flg;
8679 
8680     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8681     if (w) {
8682       PetscInt My, Ny, Mw, Nw;
8683 
8684       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8685       PetscCall(MatGetSize(*y, &My, &Ny));
8686       PetscCall(MatGetSize(w, &Mw, &Nw));
8687       if (!flg || My != Mw || Ny != Nw) w = NULL;
8688     }
8689     if (!w) {
8690       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8691       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8692       PetscCall(PetscObjectDereference((PetscObject)w));
8693     } else {
8694       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8695     }
8696   }
8697   if (!trans) {
8698     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8699   } else {
8700     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8701   }
8702   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8703   PetscFunctionReturn(PETSC_SUCCESS);
8704 }
8705 
8706 /*@
8707    MatMatInterpolate - Y = A*X or A'*X
8708 
8709    Neighbor-wise Collective
8710 
8711    Input Parameters:
8712 +  mat   - the matrix
8713 -  x - the input dense matrix
8714 
8715    Output Parameter:
8716 .  y - the output dense matrix
8717 
8718    Level: intermediate
8719 
8720    Note:
8721     This allows one to use either the restriction or interpolation (its transpose)
8722     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8723     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8724 
8725 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8726 @*/
8727 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8728 {
8729   PetscFunctionBegin;
8730   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8731   PetscFunctionReturn(PETSC_SUCCESS);
8732 }
8733 
8734 /*@
8735    MatMatRestrict - Y = A*X or A'*X
8736 
8737    Neighbor-wise Collective
8738 
8739    Input Parameters:
8740 +  mat   - the matrix
8741 -  x - the input dense matrix
8742 
8743    Output Parameter:
8744 .  y - the output dense matrix
8745 
8746    Level: intermediate
8747 
8748    Note:
8749     This allows one to use either the restriction or interpolation (its transpose)
8750     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8751     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8752 
8753 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8754 @*/
8755 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8756 {
8757   PetscFunctionBegin;
8758   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8759   PetscFunctionReturn(PETSC_SUCCESS);
8760 }
8761 
8762 /*@
8763    MatGetNullSpace - retrieves the null space of a matrix.
8764 
8765    Logically Collective
8766 
8767    Input Parameters:
8768 +  mat - the matrix
8769 -  nullsp - the null space object
8770 
8771    Level: developer
8772 
8773 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8774 @*/
8775 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8776 {
8777   PetscFunctionBegin;
8778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8779   PetscValidPointer(nullsp, 2);
8780   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8781   PetscFunctionReturn(PETSC_SUCCESS);
8782 }
8783 
8784 /*@
8785    MatSetNullSpace - attaches a null space to a matrix.
8786 
8787    Logically Collective
8788 
8789    Input Parameters:
8790 +  mat - the matrix
8791 -  nullsp - the null space object
8792 
8793    Level: advanced
8794 
8795    Notes:
8796       This null space is used by the `KSP` linear solvers to solve singular systems.
8797 
8798       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`
8799 
8800       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
8801       to zero but the linear system will still be solved in a least squares sense.
8802 
8803       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8804    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).
8805    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
8806    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
8807    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).
8808    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8809 
8810     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8811     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8812     routine also automatically calls `MatSetTransposeNullSpace()`.
8813 
8814     The user should call `MatNullSpaceDestroy()`.
8815 
8816 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8817           `KSPSetPCSide()`
8818 @*/
8819 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8820 {
8821   PetscFunctionBegin;
8822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8823   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8824   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8825   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8826   mat->nullsp = nullsp;
8827   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8828   PetscFunctionReturn(PETSC_SUCCESS);
8829 }
8830 
8831 /*@
8832    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8833 
8834    Logically Collective
8835 
8836    Input Parameters:
8837 +  mat - the matrix
8838 -  nullsp - the null space object
8839 
8840    Level: developer
8841 
8842 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8843 @*/
8844 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8845 {
8846   PetscFunctionBegin;
8847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8848   PetscValidType(mat, 1);
8849   PetscValidPointer(nullsp, 2);
8850   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8851   PetscFunctionReturn(PETSC_SUCCESS);
8852 }
8853 
8854 /*@
8855    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8856 
8857    Logically Collective
8858 
8859    Input Parameters:
8860 +  mat - the matrix
8861 -  nullsp - the null space object
8862 
8863    Level: advanced
8864 
8865    Notes:
8866    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8867 
8868    See `MatSetNullSpace()`
8869 
8870 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8871 @*/
8872 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8873 {
8874   PetscFunctionBegin;
8875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8876   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8877   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8878   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8879   mat->transnullsp = nullsp;
8880   PetscFunctionReturn(PETSC_SUCCESS);
8881 }
8882 
8883 /*@
8884    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8885         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8886 
8887    Logically Collective
8888 
8889    Input Parameters:
8890 +  mat - the matrix
8891 -  nullsp - the null space object
8892 
8893    Level: advanced
8894 
8895    Notes:
8896    Overwrites any previous near null space that may have been attached
8897 
8898    You can remove the null space by calling this routine with an nullsp of `NULL`
8899 
8900 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8901 @*/
8902 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8903 {
8904   PetscFunctionBegin;
8905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8906   PetscValidType(mat, 1);
8907   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8908   MatCheckPreallocated(mat, 1);
8909   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8910   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8911   mat->nearnullsp = nullsp;
8912   PetscFunctionReturn(PETSC_SUCCESS);
8913 }
8914 
8915 /*@
8916    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8917 
8918    Not Collective
8919 
8920    Input Parameter:
8921 .  mat - the matrix
8922 
8923    Output Parameter:
8924 .  nullsp - the null space object, `NULL` if not set
8925 
8926    Level: advanced
8927 
8928 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8929 @*/
8930 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8931 {
8932   PetscFunctionBegin;
8933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8934   PetscValidType(mat, 1);
8935   PetscValidPointer(nullsp, 2);
8936   MatCheckPreallocated(mat, 1);
8937   *nullsp = mat->nearnullsp;
8938   PetscFunctionReturn(PETSC_SUCCESS);
8939 }
8940 
8941 /*@C
8942    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8943 
8944    Collective
8945 
8946    Input Parameters:
8947 +  mat - the matrix
8948 .  row - row/column permutation
8949 -  info - information on desired factorization process
8950 
8951    Level: developer
8952 
8953    Notes:
8954    Probably really in-place only when level of fill is zero, otherwise allocates
8955    new space to store factored matrix and deletes previous memory.
8956 
8957    Most users should employ the `KSP` interface for linear solvers
8958    instead of working directly with matrix algebra routines such as this.
8959    See, e.g., `KSPCreate()`.
8960 
8961    Developer Note:
8962    The Fortran interface is not autogenerated as the
8963    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8964 
8965 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8966 @*/
8967 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8968 {
8969   PetscFunctionBegin;
8970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8971   PetscValidType(mat, 1);
8972   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8973   PetscValidPointer(info, 3);
8974   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8975   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8976   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8977   MatCheckPreallocated(mat, 1);
8978   PetscUseTypeMethod(mat, iccfactor, row, info);
8979   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8980   PetscFunctionReturn(PETSC_SUCCESS);
8981 }
8982 
8983 /*@
8984    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8985          ghosted ones.
8986 
8987    Not Collective
8988 
8989    Input Parameters:
8990 +  mat - the matrix
8991 -  diag - the diagonal values, including ghost ones
8992 
8993    Level: developer
8994 
8995    Notes:
8996     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8997 
8998     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8999 
9000 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
9001 @*/
9002 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9003 {
9004   PetscMPIInt size;
9005 
9006   PetscFunctionBegin;
9007   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9008   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9009   PetscValidType(mat, 1);
9010 
9011   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9012   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9013   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9014   if (size == 1) {
9015     PetscInt n, m;
9016     PetscCall(VecGetSize(diag, &n));
9017     PetscCall(MatGetSize(mat, NULL, &m));
9018     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9019     PetscCall(MatDiagonalScale(mat, NULL, diag));
9020   } else {
9021     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9022   }
9023   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9024   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9025   PetscFunctionReturn(PETSC_SUCCESS);
9026 }
9027 
9028 /*@
9029    MatGetInertia - Gets the inertia from a factored matrix
9030 
9031    Collective
9032 
9033    Input Parameter:
9034 .  mat - the matrix
9035 
9036    Output Parameters:
9037 +   nneg - number of negative eigenvalues
9038 .   nzero - number of zero eigenvalues
9039 -   npos - number of positive eigenvalues
9040 
9041    Level: advanced
9042 
9043    Note:
9044     Matrix must have been factored by `MatCholeskyFactor()`
9045 
9046 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9047 @*/
9048 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9049 {
9050   PetscFunctionBegin;
9051   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9052   PetscValidType(mat, 1);
9053   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9054   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9055   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9056   PetscFunctionReturn(PETSC_SUCCESS);
9057 }
9058 
9059 /*@C
9060    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9061 
9062    Neighbor-wise Collective
9063 
9064    Input Parameters:
9065 +  mat - the factored matrix obtained with `MatGetFactor()`
9066 -  b - the right-hand-side vectors
9067 
9068    Output Parameter:
9069 .  x - the result vectors
9070 
9071    Level: developer
9072 
9073    Note:
9074    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9075    call `MatSolves`(A,x,x).
9076 
9077 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9078 @*/
9079 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9080 {
9081   PetscFunctionBegin;
9082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9083   PetscValidType(mat, 1);
9084   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9085   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9086   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9087 
9088   MatCheckPreallocated(mat, 1);
9089   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9090   PetscUseTypeMethod(mat, solves, b, x);
9091   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9092   PetscFunctionReturn(PETSC_SUCCESS);
9093 }
9094 
9095 /*@
9096    MatIsSymmetric - Test whether a matrix is symmetric
9097 
9098    Collective
9099 
9100    Input Parameters:
9101 +  A - the matrix to test
9102 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9103 
9104    Output Parameter:
9105 .  flg - the result
9106 
9107    Level: intermediate
9108 
9109    Notes:
9110     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9111 
9112     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9113 
9114     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9115     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9116 
9117 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9118           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9119 @*/
9120 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9121 {
9122   PetscFunctionBegin;
9123   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9124   PetscValidBoolPointer(flg, 3);
9125 
9126   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9127   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9128   else {
9129     if (!A->ops->issymmetric) {
9130       MatType mattype;
9131       PetscCall(MatGetType(A, &mattype));
9132       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9133     }
9134     PetscUseTypeMethod(A, issymmetric, tol, flg);
9135     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9136   }
9137   PetscFunctionReturn(PETSC_SUCCESS);
9138 }
9139 
9140 /*@
9141    MatIsHermitian - Test whether a matrix is Hermitian
9142 
9143    Collective
9144 
9145    Input Parameters:
9146 +  A - the matrix to test
9147 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9148 
9149    Output Parameter:
9150 .  flg - the result
9151 
9152    Level: intermediate
9153 
9154    Notes:
9155     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9156 
9157     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9158 
9159     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9160     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9161 
9162 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9163           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9164 @*/
9165 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9166 {
9167   PetscFunctionBegin;
9168   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9169   PetscValidBoolPointer(flg, 3);
9170 
9171   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9172   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9173   else {
9174     if (!A->ops->ishermitian) {
9175       MatType mattype;
9176       PetscCall(MatGetType(A, &mattype));
9177       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9178     }
9179     PetscUseTypeMethod(A, ishermitian, tol, flg);
9180     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9181   }
9182   PetscFunctionReturn(PETSC_SUCCESS);
9183 }
9184 
9185 /*@
9186    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9187 
9188    Not Collective
9189 
9190    Input Parameter:
9191 .  A - the matrix to check
9192 
9193    Output Parameters:
9194 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9195 -  flg - the result (only valid if set is `PETSC_TRUE`)
9196 
9197    Level: advanced
9198 
9199    Notes:
9200    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9201    if you want it explicitly checked
9202 
9203     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9204     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9205 
9206 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9207 @*/
9208 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9209 {
9210   PetscFunctionBegin;
9211   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9212   PetscValidBoolPointer(set, 2);
9213   PetscValidBoolPointer(flg, 3);
9214   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9215     *set = PETSC_TRUE;
9216     *flg = PetscBool3ToBool(A->symmetric);
9217   } else {
9218     *set = PETSC_FALSE;
9219   }
9220   PetscFunctionReturn(PETSC_SUCCESS);
9221 }
9222 
9223 /*@
9224    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9225 
9226    Not Collective
9227 
9228    Input Parameter:
9229 .  A - the matrix to check
9230 
9231    Output Parameters:
9232 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9233 -  flg - the result (only valid if set is `PETSC_TRUE`)
9234 
9235    Level: advanced
9236 
9237    Notes:
9238    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9239 
9240    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9241    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9242 
9243 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9244 @*/
9245 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9246 {
9247   PetscFunctionBegin;
9248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9249   PetscValidBoolPointer(set, 2);
9250   PetscValidBoolPointer(flg, 3);
9251   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9252     *set = PETSC_TRUE;
9253     *flg = PetscBool3ToBool(A->spd);
9254   } else {
9255     *set = PETSC_FALSE;
9256   }
9257   PetscFunctionReturn(PETSC_SUCCESS);
9258 }
9259 
9260 /*@
9261    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9262 
9263    Not Collective
9264 
9265    Input Parameter:
9266 .  A - the matrix to check
9267 
9268    Output Parameters:
9269 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9270 -  flg - the result (only valid if set is `PETSC_TRUE`)
9271 
9272    Level: advanced
9273 
9274    Notes:
9275    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9276    if you want it explicitly checked
9277 
9278    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9279    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9280 
9281 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9282 @*/
9283 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9284 {
9285   PetscFunctionBegin;
9286   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9287   PetscValidBoolPointer(set, 2);
9288   PetscValidBoolPointer(flg, 3);
9289   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9290     *set = PETSC_TRUE;
9291     *flg = PetscBool3ToBool(A->hermitian);
9292   } else {
9293     *set = PETSC_FALSE;
9294   }
9295   PetscFunctionReturn(PETSC_SUCCESS);
9296 }
9297 
9298 /*@
9299    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9300 
9301    Collective
9302 
9303    Input Parameter:
9304 .  A - the matrix to test
9305 
9306    Output Parameter:
9307 .  flg - the result
9308 
9309    Level: intermediate
9310 
9311    Notes:
9312    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9313 
9314    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
9315    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9316 
9317 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9318 @*/
9319 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9320 {
9321   PetscFunctionBegin;
9322   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9323   PetscValidBoolPointer(flg, 2);
9324   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9325     *flg = PetscBool3ToBool(A->structurally_symmetric);
9326   } else {
9327     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9328     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9329   }
9330   PetscFunctionReturn(PETSC_SUCCESS);
9331 }
9332 
9333 /*@
9334    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9335 
9336    Not Collective
9337 
9338    Input Parameter:
9339 .  A - the matrix to check
9340 
9341    Output Parameters:
9342 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9343 -  flg - the result (only valid if set is PETSC_TRUE)
9344 
9345    Level: advanced
9346 
9347    Notes:
9348    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
9349    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9350 
9351    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9352 
9353 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9354 @*/
9355 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9356 {
9357   PetscFunctionBegin;
9358   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9359   PetscValidBoolPointer(set, 2);
9360   PetscValidBoolPointer(flg, 3);
9361   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9362     *set = PETSC_TRUE;
9363     *flg = PetscBool3ToBool(A->structurally_symmetric);
9364   } else {
9365     *set = PETSC_FALSE;
9366   }
9367   PetscFunctionReturn(PETSC_SUCCESS);
9368 }
9369 
9370 /*@
9371    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9372        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9373 
9374     Not Collective
9375 
9376    Input Parameter:
9377 .   mat - the matrix
9378 
9379    Output Parameters:
9380 +   nstash   - the size of the stash
9381 .   reallocs - the number of additional mallocs incurred.
9382 .   bnstash   - the size of the block stash
9383 -   breallocs - the number of additional mallocs incurred.in the block stash
9384 
9385    Level: advanced
9386 
9387 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9388 @*/
9389 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9390 {
9391   PetscFunctionBegin;
9392   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9393   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9394   PetscFunctionReturn(PETSC_SUCCESS);
9395 }
9396 
9397 /*@C
9398    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9399    parallel layout, `PetscLayout` for rows and columns
9400 
9401    Collective
9402 
9403    Input Parameter:
9404 .  mat - the matrix
9405 
9406    Output Parameters:
9407 +   right - (optional) vector that the matrix can be multiplied against
9408 -   left - (optional) vector that the matrix vector product can be stored in
9409 
9410   Level: advanced
9411 
9412    Notes:
9413     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()`.
9414 
9415     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9416 
9417 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9418 @*/
9419 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9420 {
9421   PetscFunctionBegin;
9422   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9423   PetscValidType(mat, 1);
9424   if (mat->ops->getvecs) {
9425     PetscUseTypeMethod(mat, getvecs, right, left);
9426   } else {
9427     PetscInt rbs, cbs;
9428     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9429     if (right) {
9430       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9431       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9432       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9433       PetscCall(VecSetBlockSize(*right, cbs));
9434       PetscCall(VecSetType(*right, mat->defaultvectype));
9435 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9436       if (mat->boundtocpu && mat->bindingpropagates) {
9437         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9438         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9439       }
9440 #endif
9441       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9442     }
9443     if (left) {
9444       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9445       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9446       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9447       PetscCall(VecSetBlockSize(*left, rbs));
9448       PetscCall(VecSetType(*left, mat->defaultvectype));
9449 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9450       if (mat->boundtocpu && mat->bindingpropagates) {
9451         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9452         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9453       }
9454 #endif
9455       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9456     }
9457   }
9458   PetscFunctionReturn(PETSC_SUCCESS);
9459 }
9460 
9461 /*@C
9462    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9463      with default values.
9464 
9465    Not Collective
9466 
9467    Input Parameter:
9468 .    info - the `MatFactorInfo` data structure
9469 
9470    Level: developer
9471 
9472    Notes:
9473     The solvers are generally used through the `KSP` and `PC` objects, for example
9474           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9475 
9476     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9477 
9478    Developer Note:
9479    The Fortran interface is not autogenerated as the
9480    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9481 
9482 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9483 @*/
9484 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9485 {
9486   PetscFunctionBegin;
9487   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9488   PetscFunctionReturn(PETSC_SUCCESS);
9489 }
9490 
9491 /*@
9492    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9493 
9494    Collective
9495 
9496    Input Parameters:
9497 +  mat - the factored matrix
9498 -  is - the index set defining the Schur indices (0-based)
9499 
9500    Level: advanced
9501 
9502    Notes:
9503     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9504 
9505    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9506 
9507    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9508 
9509 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9510           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9511 @*/
9512 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9513 {
9514   PetscErrorCode (*f)(Mat, IS);
9515 
9516   PetscFunctionBegin;
9517   PetscValidType(mat, 1);
9518   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9519   PetscValidType(is, 2);
9520   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9521   PetscCheckSameComm(mat, 1, is, 2);
9522   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9523   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9524   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9525   PetscCall(MatDestroy(&mat->schur));
9526   PetscCall((*f)(mat, is));
9527   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9528   PetscFunctionReturn(PETSC_SUCCESS);
9529 }
9530 
9531 /*@
9532   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9533 
9534    Logically Collective
9535 
9536    Input Parameters:
9537 +  F - the factored matrix obtained by calling `MatGetFactor()`
9538 .  S - location where to return the Schur complement, can be `NULL`
9539 -  status - the status of the Schur complement matrix, can be `NULL`
9540 
9541    Level: advanced
9542 
9543    Notes:
9544    You must call `MatFactorSetSchurIS()` before calling this routine.
9545 
9546    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9547 
9548    The routine provides a copy of the Schur matrix stored within the solver data structures.
9549    The caller must destroy the object when it is no longer needed.
9550    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9551 
9552    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)
9553 
9554    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9555 
9556    Developer Note:
9557     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9558    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9559 
9560 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9561 @*/
9562 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9563 {
9564   PetscFunctionBegin;
9565   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9566   if (S) PetscValidPointer(S, 2);
9567   if (status) PetscValidPointer(status, 3);
9568   if (S) {
9569     PetscErrorCode (*f)(Mat, Mat *);
9570 
9571     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9572     if (f) {
9573       PetscCall((*f)(F, S));
9574     } else {
9575       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9576     }
9577   }
9578   if (status) *status = F->schur_status;
9579   PetscFunctionReturn(PETSC_SUCCESS);
9580 }
9581 
9582 /*@
9583   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9584 
9585    Logically Collective
9586 
9587    Input Parameters:
9588 +  F - the factored matrix obtained by calling `MatGetFactor()`
9589 .  *S - location where to return the Schur complement, can be `NULL`
9590 -  status - the status of the Schur complement matrix, can be `NULL`
9591 
9592    Level: advanced
9593 
9594    Notes:
9595    You must call `MatFactorSetSchurIS()` before calling this routine.
9596 
9597    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9598 
9599    The routine returns a the Schur Complement stored within the data structures of the solver.
9600 
9601    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9602 
9603    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9604 
9605    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9606 
9607    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9608 
9609 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9610 @*/
9611 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9612 {
9613   PetscFunctionBegin;
9614   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9615   if (S) PetscValidPointer(S, 2);
9616   if (status) PetscValidPointer(status, 3);
9617   if (S) *S = F->schur;
9618   if (status) *status = F->schur_status;
9619   PetscFunctionReturn(PETSC_SUCCESS);
9620 }
9621 
9622 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9623 {
9624   Mat S = F->schur;
9625 
9626   PetscFunctionBegin;
9627   switch (F->schur_status) {
9628   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9629   case MAT_FACTOR_SCHUR_INVERTED:
9630     if (S) {
9631       S->ops->solve             = NULL;
9632       S->ops->matsolve          = NULL;
9633       S->ops->solvetranspose    = NULL;
9634       S->ops->matsolvetranspose = NULL;
9635       S->ops->solveadd          = NULL;
9636       S->ops->solvetransposeadd = NULL;
9637       S->factortype             = MAT_FACTOR_NONE;
9638       PetscCall(PetscFree(S->solvertype));
9639     }
9640   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9641     break;
9642   default:
9643     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9644   }
9645   PetscFunctionReturn(PETSC_SUCCESS);
9646 }
9647 
9648 /*@
9649   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9650 
9651    Logically Collective
9652 
9653    Input Parameters:
9654 +  F - the factored matrix obtained by calling `MatGetFactor()`
9655 .  *S - location where the Schur complement is stored
9656 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9657 
9658    Level: advanced
9659 
9660 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9661 @*/
9662 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9663 {
9664   PetscFunctionBegin;
9665   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9666   if (S) {
9667     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9668     *S = NULL;
9669   }
9670   F->schur_status = status;
9671   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9672   PetscFunctionReturn(PETSC_SUCCESS);
9673 }
9674 
9675 /*@
9676   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9677 
9678    Logically Collective
9679 
9680    Input Parameters:
9681 +  F - the factored matrix obtained by calling `MatGetFactor()`
9682 .  rhs - location where the right hand side of the Schur complement system is stored
9683 -  sol - location where the solution of the Schur complement system has to be returned
9684 
9685    Level: advanced
9686 
9687    Notes:
9688    The sizes of the vectors should match the size of the Schur complement
9689 
9690    Must be called after `MatFactorSetSchurIS()`
9691 
9692 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9693 @*/
9694 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9695 {
9696   PetscFunctionBegin;
9697   PetscValidType(F, 1);
9698   PetscValidType(rhs, 2);
9699   PetscValidType(sol, 3);
9700   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9701   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9702   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9703   PetscCheckSameComm(F, 1, rhs, 2);
9704   PetscCheckSameComm(F, 1, sol, 3);
9705   PetscCall(MatFactorFactorizeSchurComplement(F));
9706   switch (F->schur_status) {
9707   case MAT_FACTOR_SCHUR_FACTORED:
9708     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9709     break;
9710   case MAT_FACTOR_SCHUR_INVERTED:
9711     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9712     break;
9713   default:
9714     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9715   }
9716   PetscFunctionReturn(PETSC_SUCCESS);
9717 }
9718 
9719 /*@
9720   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9721 
9722    Logically Collective
9723 
9724    Input Parameters:
9725 +  F - the factored matrix obtained by calling `MatGetFactor()`
9726 .  rhs - location where the right hand side of the Schur complement system is stored
9727 -  sol - location where the solution of the Schur complement system has to be returned
9728 
9729    Level: advanced
9730 
9731    Notes:
9732    The sizes of the vectors should match the size of the Schur complement
9733 
9734    Must be called after `MatFactorSetSchurIS()`
9735 
9736 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9737 @*/
9738 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9739 {
9740   PetscFunctionBegin;
9741   PetscValidType(F, 1);
9742   PetscValidType(rhs, 2);
9743   PetscValidType(sol, 3);
9744   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9745   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9746   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9747   PetscCheckSameComm(F, 1, rhs, 2);
9748   PetscCheckSameComm(F, 1, sol, 3);
9749   PetscCall(MatFactorFactorizeSchurComplement(F));
9750   switch (F->schur_status) {
9751   case MAT_FACTOR_SCHUR_FACTORED:
9752     PetscCall(MatSolve(F->schur, rhs, sol));
9753     break;
9754   case MAT_FACTOR_SCHUR_INVERTED:
9755     PetscCall(MatMult(F->schur, rhs, sol));
9756     break;
9757   default:
9758     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9759   }
9760   PetscFunctionReturn(PETSC_SUCCESS);
9761 }
9762 
9763 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9764 #if PetscDefined(HAVE_CUDA)
9765 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9766 #endif
9767 
9768 /* Schur status updated in the interface */
9769 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9770 {
9771   Mat S = F->schur;
9772 
9773   PetscFunctionBegin;
9774   if (S) {
9775     PetscMPIInt size;
9776     PetscBool   isdense, isdensecuda;
9777 
9778     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9779     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9780     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9781     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9782     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9783     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9784     if (isdense) {
9785       PetscCall(MatSeqDenseInvertFactors_Private(S));
9786     } else if (isdensecuda) {
9787 #if defined(PETSC_HAVE_CUDA)
9788       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9789 #endif
9790     }
9791     // HIP??????????????
9792     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9793   }
9794   PetscFunctionReturn(PETSC_SUCCESS);
9795 }
9796 
9797 /*@
9798   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9799 
9800    Logically Collective
9801 
9802    Input Parameter:
9803 .  F - the factored matrix obtained by calling `MatGetFactor()`
9804 
9805    Level: advanced
9806 
9807    Notes:
9808     Must be called after `MatFactorSetSchurIS()`.
9809 
9810    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9811 
9812 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9813 @*/
9814 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9815 {
9816   PetscFunctionBegin;
9817   PetscValidType(F, 1);
9818   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9819   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9820   PetscCall(MatFactorFactorizeSchurComplement(F));
9821   PetscCall(MatFactorInvertSchurComplement_Private(F));
9822   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9823   PetscFunctionReturn(PETSC_SUCCESS);
9824 }
9825 
9826 /*@
9827   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9828 
9829    Logically Collective
9830 
9831    Input Parameter:
9832 .  F - the factored matrix obtained by calling `MatGetFactor()`
9833 
9834    Level: advanced
9835 
9836    Note:
9837     Must be called after `MatFactorSetSchurIS()`
9838 
9839 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9840 @*/
9841 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9842 {
9843   MatFactorInfo info;
9844 
9845   PetscFunctionBegin;
9846   PetscValidType(F, 1);
9847   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9848   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9849   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9850   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9851   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9852     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9853   } else {
9854     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9855   }
9856   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9857   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9858   PetscFunctionReturn(PETSC_SUCCESS);
9859 }
9860 
9861 /*@
9862    MatPtAP - Creates the matrix product C = P^T * A * P
9863 
9864    Neighbor-wise Collective
9865 
9866    Input Parameters:
9867 +  A - the matrix
9868 .  P - the projection matrix
9869 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9870 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9871           if the result is a dense matrix this is irrelevant
9872 
9873    Output Parameter:
9874 .  C - the product matrix
9875 
9876    Level: intermediate
9877 
9878    Notes:
9879    C will be created and must be destroyed by the user with `MatDestroy()`.
9880 
9881    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9882 
9883    Developer Note:
9884    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9885 
9886 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9887 @*/
9888 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9889 {
9890   PetscFunctionBegin;
9891   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9892   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9893 
9894   if (scall == MAT_INITIAL_MATRIX) {
9895     PetscCall(MatProductCreate(A, P, NULL, C));
9896     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9897     PetscCall(MatProductSetAlgorithm(*C, "default"));
9898     PetscCall(MatProductSetFill(*C, fill));
9899 
9900     (*C)->product->api_user = PETSC_TRUE;
9901     PetscCall(MatProductSetFromOptions(*C));
9902     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);
9903     PetscCall(MatProductSymbolic(*C));
9904   } else { /* scall == MAT_REUSE_MATRIX */
9905     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9906   }
9907 
9908   PetscCall(MatProductNumeric(*C));
9909   (*C)->symmetric = A->symmetric;
9910   (*C)->spd       = A->spd;
9911   PetscFunctionReturn(PETSC_SUCCESS);
9912 }
9913 
9914 /*@
9915    MatRARt - Creates the matrix product C = R * A * R^T
9916 
9917    Neighbor-wise Collective
9918 
9919    Input Parameters:
9920 +  A - the matrix
9921 .  R - the projection matrix
9922 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9923 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9924           if the result is a dense matrix this is irrelevant
9925 
9926    Output Parameter:
9927 .  C - the product matrix
9928 
9929    Level: intermediate
9930 
9931    Notes:
9932    C will be created and must be destroyed by the user with `MatDestroy()`.
9933 
9934    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9935 
9936    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9937    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9938    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9939    We recommend using MatPtAP().
9940 
9941 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9942 @*/
9943 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9944 {
9945   PetscFunctionBegin;
9946   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9947   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9948 
9949   if (scall == MAT_INITIAL_MATRIX) {
9950     PetscCall(MatProductCreate(A, R, NULL, C));
9951     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9952     PetscCall(MatProductSetAlgorithm(*C, "default"));
9953     PetscCall(MatProductSetFill(*C, fill));
9954 
9955     (*C)->product->api_user = PETSC_TRUE;
9956     PetscCall(MatProductSetFromOptions(*C));
9957     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);
9958     PetscCall(MatProductSymbolic(*C));
9959   } else { /* scall == MAT_REUSE_MATRIX */
9960     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9961   }
9962 
9963   PetscCall(MatProductNumeric(*C));
9964   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9965   PetscFunctionReturn(PETSC_SUCCESS);
9966 }
9967 
9968 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9969 {
9970   PetscFunctionBegin;
9971   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9972 
9973   if (scall == MAT_INITIAL_MATRIX) {
9974     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9975     PetscCall(MatProductCreate(A, B, NULL, C));
9976     PetscCall(MatProductSetType(*C, ptype));
9977     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9978     PetscCall(MatProductSetFill(*C, fill));
9979 
9980     (*C)->product->api_user = PETSC_TRUE;
9981     PetscCall(MatProductSetFromOptions(*C));
9982     PetscCall(MatProductSymbolic(*C));
9983   } else { /* scall == MAT_REUSE_MATRIX */
9984     Mat_Product *product = (*C)->product;
9985     PetscBool    isdense;
9986 
9987     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9988     if (isdense && product && product->type != ptype) {
9989       PetscCall(MatProductClear(*C));
9990       product = NULL;
9991     }
9992     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9993     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9994       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9995       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9996       product           = (*C)->product;
9997       product->fill     = fill;
9998       product->api_user = PETSC_TRUE;
9999       product->clear    = PETSC_TRUE;
10000 
10001       PetscCall(MatProductSetType(*C, ptype));
10002       PetscCall(MatProductSetFromOptions(*C));
10003       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);
10004       PetscCall(MatProductSymbolic(*C));
10005     } else { /* user may change input matrices A or B when REUSE */
10006       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10007     }
10008   }
10009   PetscCall(MatProductNumeric(*C));
10010   PetscFunctionReturn(PETSC_SUCCESS);
10011 }
10012 
10013 /*@
10014    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10015 
10016    Neighbor-wise Collective
10017 
10018    Input Parameters:
10019 +  A - the left matrix
10020 .  B - the right matrix
10021 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10022 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10023           if the result is a dense matrix this is irrelevant
10024 
10025    Output Parameter:
10026 .  C - the product matrix
10027 
10028    Notes:
10029    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10030 
10031    `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
10032    call to this function with `MAT_INITIAL_MATRIX`.
10033 
10034    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10035 
10036    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`,
10037    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10038 
10039    Example of Usage:
10040 .vb
10041      MatProductCreate(A,B,NULL,&C);
10042      MatProductSetType(C,MATPRODUCT_AB);
10043      MatProductSymbolic(C);
10044      MatProductNumeric(C); // compute C=A * B
10045      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10046      MatProductNumeric(C);
10047      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10048      MatProductNumeric(C);
10049 .ve
10050 
10051    Level: intermediate
10052 
10053 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10054 @*/
10055 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10056 {
10057   PetscFunctionBegin;
10058   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10059   PetscFunctionReturn(PETSC_SUCCESS);
10060 }
10061 
10062 /*@
10063    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10064 
10065    Neighbor-wise Collective
10066 
10067    Input Parameters:
10068 +  A - the left matrix
10069 .  B - the right matrix
10070 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10071 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10072 
10073    Output Parameter:
10074 .  C - the product matrix
10075 
10076    Level: intermediate
10077 
10078    Notes:
10079    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10080 
10081    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10082 
10083    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10084    actually needed.
10085 
10086    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10087    and for pairs of `MATMPIDENSE` matrices.
10088 
10089    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10090 
10091    Options Database Keys:
10092 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10093               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10094               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10095 
10096 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10097 @*/
10098 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10099 {
10100   PetscFunctionBegin;
10101   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10102   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10103   PetscFunctionReturn(PETSC_SUCCESS);
10104 }
10105 
10106 /*@
10107    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10108 
10109    Neighbor-wise Collective
10110 
10111    Input Parameters:
10112 +  A - the left matrix
10113 .  B - the right matrix
10114 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10115 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10116 
10117    Output Parameter:
10118 .  C - the product matrix
10119 
10120    Level: intermediate
10121 
10122    Notes:
10123    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10124 
10125    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10126 
10127    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10128 
10129    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10130    actually needed.
10131 
10132    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10133    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10134 
10135 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10136 @*/
10137 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10138 {
10139   PetscFunctionBegin;
10140   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10141   PetscFunctionReturn(PETSC_SUCCESS);
10142 }
10143 
10144 /*@
10145    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10146 
10147    Neighbor-wise Collective
10148 
10149    Input Parameters:
10150 +  A - the left matrix
10151 .  B - the middle matrix
10152 .  C - the right matrix
10153 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10154 -  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
10155           if the result is a dense matrix this is irrelevant
10156 
10157    Output Parameter:
10158 .  D - the product matrix
10159 
10160    Level: intermediate
10161 
10162    Notes:
10163    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10164 
10165    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10166 
10167    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10168 
10169    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10170    actually needed.
10171 
10172    If you have many matrices with the same non-zero structure to multiply, you
10173    should use `MAT_REUSE_MATRIX` in all calls but the first
10174 
10175 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10176 @*/
10177 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10178 {
10179   PetscFunctionBegin;
10180   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10181   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10182 
10183   if (scall == MAT_INITIAL_MATRIX) {
10184     PetscCall(MatProductCreate(A, B, C, D));
10185     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10186     PetscCall(MatProductSetAlgorithm(*D, "default"));
10187     PetscCall(MatProductSetFill(*D, fill));
10188 
10189     (*D)->product->api_user = PETSC_TRUE;
10190     PetscCall(MatProductSetFromOptions(*D));
10191     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,
10192                ((PetscObject)C)->type_name);
10193     PetscCall(MatProductSymbolic(*D));
10194   } else { /* user may change input matrices when REUSE */
10195     PetscCall(MatProductReplaceMats(A, B, C, *D));
10196   }
10197   PetscCall(MatProductNumeric(*D));
10198   PetscFunctionReturn(PETSC_SUCCESS);
10199 }
10200 
10201 /*@
10202    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10203 
10204    Collective
10205 
10206    Input Parameters:
10207 +  mat - the matrix
10208 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10209 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10210 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10211 
10212    Output Parameter:
10213 .  matredundant - redundant matrix
10214 
10215    Level: advanced
10216 
10217    Notes:
10218    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10219    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10220 
10221    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10222    calling it.
10223 
10224    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10225 
10226 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10227 @*/
10228 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10229 {
10230   MPI_Comm       comm;
10231   PetscMPIInt    size;
10232   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10233   Mat_Redundant *redund     = NULL;
10234   PetscSubcomm   psubcomm   = NULL;
10235   MPI_Comm       subcomm_in = subcomm;
10236   Mat           *matseq;
10237   IS             isrow, iscol;
10238   PetscBool      newsubcomm = PETSC_FALSE;
10239 
10240   PetscFunctionBegin;
10241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10242   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10243     PetscValidPointer(*matredundant, 5);
10244     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10245   }
10246 
10247   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10248   if (size == 1 || nsubcomm == 1) {
10249     if (reuse == MAT_INITIAL_MATRIX) {
10250       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10251     } else {
10252       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");
10253       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10254     }
10255     PetscFunctionReturn(PETSC_SUCCESS);
10256   }
10257 
10258   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10259   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10260   MatCheckPreallocated(mat, 1);
10261 
10262   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10263   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10264     /* create psubcomm, then get subcomm */
10265     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10266     PetscCallMPI(MPI_Comm_size(comm, &size));
10267     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10268 
10269     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10270     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10271     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10272     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10273     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10274     newsubcomm = PETSC_TRUE;
10275     PetscCall(PetscSubcommDestroy(&psubcomm));
10276   }
10277 
10278   /* get isrow, iscol and a local sequential matrix matseq[0] */
10279   if (reuse == MAT_INITIAL_MATRIX) {
10280     mloc_sub = PETSC_DECIDE;
10281     nloc_sub = PETSC_DECIDE;
10282     if (bs < 1) {
10283       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10284       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10285     } else {
10286       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10287       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10288     }
10289     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10290     rstart = rend - mloc_sub;
10291     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10292     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10293   } else { /* reuse == MAT_REUSE_MATRIX */
10294     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");
10295     /* retrieve subcomm */
10296     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10297     redund = (*matredundant)->redundant;
10298     isrow  = redund->isrow;
10299     iscol  = redund->iscol;
10300     matseq = redund->matseq;
10301   }
10302   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10303 
10304   /* get matredundant over subcomm */
10305   if (reuse == MAT_INITIAL_MATRIX) {
10306     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10307 
10308     /* create a supporting struct and attach it to C for reuse */
10309     PetscCall(PetscNew(&redund));
10310     (*matredundant)->redundant = redund;
10311     redund->isrow              = isrow;
10312     redund->iscol              = iscol;
10313     redund->matseq             = matseq;
10314     if (newsubcomm) {
10315       redund->subcomm = subcomm;
10316     } else {
10317       redund->subcomm = MPI_COMM_NULL;
10318     }
10319   } else {
10320     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10321   }
10322 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10323   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10324     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10325     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10326   }
10327 #endif
10328   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10329   PetscFunctionReturn(PETSC_SUCCESS);
10330 }
10331 
10332 /*@C
10333    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10334    a given `Mat`. Each submatrix can span multiple procs.
10335 
10336    Collective
10337 
10338    Input Parameters:
10339 +  mat - the matrix
10340 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10341 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10342 
10343    Output Parameter:
10344 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10345 
10346   Level: advanced
10347 
10348   Notes:
10349   The submatrix partition across processors is dictated by `subComm` a
10350   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10351   is not restricted to be grouped with consecutive original ranks.
10352 
10353   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10354   map directly to the layout of the original matrix [wrt the local
10355   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10356   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10357   the `subMat`. However the offDiagMat looses some columns - and this is
10358   reconstructed with `MatSetValues()`
10359 
10360   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10361 
10362 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10363 @*/
10364 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10365 {
10366   PetscMPIInt commsize, subCommSize;
10367 
10368   PetscFunctionBegin;
10369   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10370   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10371   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10372 
10373   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");
10374   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10375   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10376   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10377   PetscFunctionReturn(PETSC_SUCCESS);
10378 }
10379 
10380 /*@
10381    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10382 
10383    Not Collective
10384 
10385    Input Parameters:
10386 +  mat - matrix to extract local submatrix from
10387 .  isrow - local row indices for submatrix
10388 -  iscol - local column indices for submatrix
10389 
10390    Output Parameter:
10391 .  submat - the submatrix
10392 
10393    Level: intermediate
10394 
10395    Notes:
10396    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10397 
10398    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10399    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10400 
10401    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10402    `MatSetValuesBlockedLocal()` will also be implemented.
10403 
10404    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10405    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10406 
10407 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10408 @*/
10409 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10410 {
10411   PetscFunctionBegin;
10412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10413   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10414   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10415   PetscCheckSameComm(isrow, 2, iscol, 3);
10416   PetscValidPointer(submat, 4);
10417   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10418 
10419   if (mat->ops->getlocalsubmatrix) {
10420     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10421   } else {
10422     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10423   }
10424   PetscFunctionReturn(PETSC_SUCCESS);
10425 }
10426 
10427 /*@
10428    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10429 
10430    Not Collective
10431 
10432    Input Parameters:
10433 +  mat - matrix to extract local submatrix from
10434 .  isrow - local row indices for submatrix
10435 .  iscol - local column indices for submatrix
10436 -  submat - the submatrix
10437 
10438    Level: intermediate
10439 
10440 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10441 @*/
10442 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10443 {
10444   PetscFunctionBegin;
10445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10446   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10447   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10448   PetscCheckSameComm(isrow, 2, iscol, 3);
10449   PetscValidPointer(submat, 4);
10450   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10451 
10452   if (mat->ops->restorelocalsubmatrix) {
10453     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10454   } else {
10455     PetscCall(MatDestroy(submat));
10456   }
10457   *submat = NULL;
10458   PetscFunctionReturn(PETSC_SUCCESS);
10459 }
10460 
10461 /*@
10462    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10463 
10464    Collective
10465 
10466    Input Parameter:
10467 .  mat - the matrix
10468 
10469    Output Parameter:
10470 .  is - if any rows have zero diagonals this contains the list of them
10471 
10472    Level: developer
10473 
10474 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10475 @*/
10476 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10477 {
10478   PetscFunctionBegin;
10479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10480   PetscValidType(mat, 1);
10481   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10482   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10483 
10484   if (!mat->ops->findzerodiagonals) {
10485     Vec                diag;
10486     const PetscScalar *a;
10487     PetscInt          *rows;
10488     PetscInt           rStart, rEnd, r, nrow = 0;
10489 
10490     PetscCall(MatCreateVecs(mat, &diag, NULL));
10491     PetscCall(MatGetDiagonal(mat, diag));
10492     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10493     PetscCall(VecGetArrayRead(diag, &a));
10494     for (r = 0; r < rEnd - rStart; ++r)
10495       if (a[r] == 0.0) ++nrow;
10496     PetscCall(PetscMalloc1(nrow, &rows));
10497     nrow = 0;
10498     for (r = 0; r < rEnd - rStart; ++r)
10499       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10500     PetscCall(VecRestoreArrayRead(diag, &a));
10501     PetscCall(VecDestroy(&diag));
10502     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10503   } else {
10504     PetscUseTypeMethod(mat, findzerodiagonals, is);
10505   }
10506   PetscFunctionReturn(PETSC_SUCCESS);
10507 }
10508 
10509 /*@
10510    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10511 
10512    Collective
10513 
10514    Input Parameter:
10515 .  mat - the matrix
10516 
10517    Output Parameter:
10518 .  is - contains the list of rows with off block diagonal entries
10519 
10520    Level: developer
10521 
10522 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10523 @*/
10524 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10525 {
10526   PetscFunctionBegin;
10527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10528   PetscValidType(mat, 1);
10529   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10530   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10531 
10532   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10533   PetscFunctionReturn(PETSC_SUCCESS);
10534 }
10535 
10536 /*@C
10537   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10538 
10539   Collective; No Fortran Support
10540 
10541   Input Parameter:
10542 . mat - the matrix
10543 
10544   Output Parameter:
10545 . values - the block inverses in column major order (FORTRAN-like)
10546 
10547   Level: advanced
10548 
10549    Notes:
10550    The size of the blocks is determined by the block size of the matrix.
10551 
10552    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10553 
10554    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10555 
10556 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10557 @*/
10558 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10559 {
10560   PetscFunctionBegin;
10561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10562   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10563   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10564   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10565   PetscFunctionReturn(PETSC_SUCCESS);
10566 }
10567 
10568 /*@C
10569   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10570 
10571   Collective; No Fortran Support
10572 
10573   Input Parameters:
10574 + mat - the matrix
10575 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10576 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10577 
10578   Output Parameter:
10579 . values - the block inverses in column major order (FORTRAN-like)
10580 
10581   Level: advanced
10582 
10583   Notes:
10584   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10585 
10586   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10587 
10588 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10589 @*/
10590 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10591 {
10592   PetscFunctionBegin;
10593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10594   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10595   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10596   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10597   PetscFunctionReturn(PETSC_SUCCESS);
10598 }
10599 
10600 /*@
10601   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10602 
10603   Collective
10604 
10605   Input Parameters:
10606 + A - the matrix
10607 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10608 
10609   Level: advanced
10610 
10611   Note:
10612   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10613 
10614 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10615 @*/
10616 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10617 {
10618   const PetscScalar *vals;
10619   PetscInt          *dnnz;
10620   PetscInt           m, rstart, rend, bs, i, j;
10621 
10622   PetscFunctionBegin;
10623   PetscCall(MatInvertBlockDiagonal(A, &vals));
10624   PetscCall(MatGetBlockSize(A, &bs));
10625   PetscCall(MatGetLocalSize(A, &m, NULL));
10626   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10627   PetscCall(PetscMalloc1(m / bs, &dnnz));
10628   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10629   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10630   PetscCall(PetscFree(dnnz));
10631   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10632   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10633   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10634   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10635   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10636   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10637   PetscFunctionReturn(PETSC_SUCCESS);
10638 }
10639 
10640 /*@C
10641     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10642     via `MatTransposeColoringCreate()`.
10643 
10644     Collective
10645 
10646     Input Parameter:
10647 .   c - coloring context
10648 
10649     Level: intermediate
10650 
10651 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10652 @*/
10653 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10654 {
10655   MatTransposeColoring matcolor = *c;
10656 
10657   PetscFunctionBegin;
10658   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10659   if (--((PetscObject)matcolor)->refct > 0) {
10660     matcolor = NULL;
10661     PetscFunctionReturn(PETSC_SUCCESS);
10662   }
10663 
10664   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10665   PetscCall(PetscFree(matcolor->rows));
10666   PetscCall(PetscFree(matcolor->den2sp));
10667   PetscCall(PetscFree(matcolor->colorforcol));
10668   PetscCall(PetscFree(matcolor->columns));
10669   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10670   PetscCall(PetscHeaderDestroy(c));
10671   PetscFunctionReturn(PETSC_SUCCESS);
10672 }
10673 
10674 /*@C
10675     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10676     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10677     `MatTransposeColoring` to sparse B.
10678 
10679     Collective
10680 
10681     Input Parameters:
10682 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10683 -   B - sparse matrix
10684 
10685     Output Parameter:
10686 .   Btdense - dense matrix B^T
10687 
10688     Level: developer
10689 
10690     Note:
10691     These are used internally for some implementations of `MatRARt()`
10692 
10693 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10694 @*/
10695 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10696 {
10697   PetscFunctionBegin;
10698   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10699   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10700   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10701 
10702   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10703   PetscFunctionReturn(PETSC_SUCCESS);
10704 }
10705 
10706 /*@C
10707     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10708     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10709     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10710     `Csp` from `Cden`.
10711 
10712     Collective
10713 
10714     Input Parameters:
10715 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10716 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10717 
10718     Output Parameter:
10719 .   Csp - sparse matrix
10720 
10721     Level: developer
10722 
10723     Note:
10724     These are used internally for some implementations of `MatRARt()`
10725 
10726 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10727 @*/
10728 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10729 {
10730   PetscFunctionBegin;
10731   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10732   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10733   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10734 
10735   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10736   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10737   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10738   PetscFunctionReturn(PETSC_SUCCESS);
10739 }
10740 
10741 /*@C
10742    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10743 
10744    Collective
10745 
10746    Input Parameters:
10747 +  mat - the matrix product C
10748 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10749 
10750     Output Parameter:
10751 .   color - the new coloring context
10752 
10753     Level: intermediate
10754 
10755 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10756           `MatTransColoringApplyDenToSp()`
10757 @*/
10758 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10759 {
10760   MatTransposeColoring c;
10761   MPI_Comm             comm;
10762 
10763   PetscFunctionBegin;
10764   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10765   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10766   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10767 
10768   c->ctype = iscoloring->ctype;
10769   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10770 
10771   *color = c;
10772   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10773   PetscFunctionReturn(PETSC_SUCCESS);
10774 }
10775 
10776 /*@
10777       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10778         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10779         same, otherwise it will be larger
10780 
10781      Not Collective
10782 
10783   Input Parameter:
10784 .    A  - the matrix
10785 
10786   Output Parameter:
10787 .    state - the current state
10788 
10789   Level: intermediate
10790 
10791   Notes:
10792     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10793          different matrices
10794 
10795     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10796 
10797     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10798 
10799 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10800 @*/
10801 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10802 {
10803   PetscFunctionBegin;
10804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10805   *state = mat->nonzerostate;
10806   PetscFunctionReturn(PETSC_SUCCESS);
10807 }
10808 
10809 /*@
10810       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10811                  matrices from each processor
10812 
10813     Collective
10814 
10815    Input Parameters:
10816 +    comm - the communicators the parallel matrix will live on
10817 .    seqmat - the input sequential matrices
10818 .    n - number of local columns (or `PETSC_DECIDE`)
10819 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10820 
10821    Output Parameter:
10822 .    mpimat - the parallel matrix generated
10823 
10824     Level: developer
10825 
10826    Note:
10827     The number of columns of the matrix in EACH processor MUST be the same.
10828 
10829 .seealso: [](chapter_matrices), `Mat`
10830 @*/
10831 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10832 {
10833   PetscMPIInt size;
10834 
10835   PetscFunctionBegin;
10836   PetscCallMPI(MPI_Comm_size(comm, &size));
10837   if (size == 1) {
10838     if (reuse == MAT_INITIAL_MATRIX) {
10839       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10840     } else {
10841       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10842     }
10843     PetscFunctionReturn(PETSC_SUCCESS);
10844   }
10845 
10846   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");
10847 
10848   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10849   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10850   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10851   PetscFunctionReturn(PETSC_SUCCESS);
10852 }
10853 
10854 /*@
10855      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10856 
10857     Collective
10858 
10859    Input Parameters:
10860 +    A   - the matrix to create subdomains from
10861 -    N   - requested number of subdomains
10862 
10863    Output Parameters:
10864 +    n   - number of subdomains resulting on this rank
10865 -    iss - `IS` list with indices of subdomains on this rank
10866 
10867     Level: advanced
10868 
10869     Note:
10870     The number of subdomains must be smaller than the communicator size
10871 
10872 .seealso: [](chapter_matrices), `Mat`, `IS`
10873 @*/
10874 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10875 {
10876   MPI_Comm    comm, subcomm;
10877   PetscMPIInt size, rank, color;
10878   PetscInt    rstart, rend, k;
10879 
10880   PetscFunctionBegin;
10881   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10882   PetscCallMPI(MPI_Comm_size(comm, &size));
10883   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10884   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);
10885   *n    = 1;
10886   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10887   color = rank / k;
10888   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10889   PetscCall(PetscMalloc1(1, iss));
10890   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10891   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10892   PetscCallMPI(MPI_Comm_free(&subcomm));
10893   PetscFunctionReturn(PETSC_SUCCESS);
10894 }
10895 
10896 /*@
10897    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10898 
10899    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10900    If they are not the same, uses `MatMatMatMult()`.
10901 
10902    Once the coarse grid problem is constructed, correct for interpolation operators
10903    that are not of full rank, which can legitimately happen in the case of non-nested
10904    geometric multigrid.
10905 
10906    Input Parameters:
10907 +  restrct - restriction operator
10908 .  dA - fine grid matrix
10909 .  interpolate - interpolation operator
10910 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10911 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10912 
10913    Output Parameter:
10914 .  A - the Galerkin coarse matrix
10915 
10916    Options Database Key:
10917 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10918 
10919    Level: developer
10920 
10921 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10922 @*/
10923 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10924 {
10925   IS  zerorows;
10926   Vec diag;
10927 
10928   PetscFunctionBegin;
10929   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10930   /* Construct the coarse grid matrix */
10931   if (interpolate == restrct) {
10932     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10933   } else {
10934     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10935   }
10936 
10937   /* If the interpolation matrix is not of full rank, A will have zero rows.
10938      This can legitimately happen in the case of non-nested geometric multigrid.
10939      In that event, we set the rows of the matrix to the rows of the identity,
10940      ignoring the equations (as the RHS will also be zero). */
10941 
10942   PetscCall(MatFindZeroRows(*A, &zerorows));
10943 
10944   if (zerorows != NULL) { /* if there are any zero rows */
10945     PetscCall(MatCreateVecs(*A, &diag, NULL));
10946     PetscCall(MatGetDiagonal(*A, diag));
10947     PetscCall(VecISSet(diag, zerorows, 1.0));
10948     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10949     PetscCall(VecDestroy(&diag));
10950     PetscCall(ISDestroy(&zerorows));
10951   }
10952   PetscFunctionReturn(PETSC_SUCCESS);
10953 }
10954 
10955 /*@C
10956     MatSetOperation - Allows user to set a matrix operation for any matrix type
10957 
10958    Logically Collective
10959 
10960     Input Parameters:
10961 +   mat - the matrix
10962 .   op - the name of the operation
10963 -   f - the function that provides the operation
10964 
10965    Level: developer
10966 
10967     Usage:
10968 .vb
10969   extern PetscErrorCode usermult(Mat, Vec, Vec);
10970 
10971   PetscCall(MatCreateXXX(comm, ..., &A));
10972   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10973 .ve
10974 
10975     Notes:
10976     See the file `include/petscmat.h` for a complete list of matrix
10977     operations, which all have the form MATOP_<OPERATION>, where
10978     <OPERATION> is the name (in all capital letters) of the
10979     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10980 
10981     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10982     sequence as the usual matrix interface routines, since they
10983     are intended to be accessed via the usual matrix interface
10984     routines, e.g.,
10985 .vb
10986   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10987 .ve
10988 
10989     In particular each function MUST return `PETSC_SUCCESS` on success and
10990     nonzero on failure.
10991 
10992     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10993 
10994 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10995 @*/
10996 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10997 {
10998   PetscFunctionBegin;
10999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11000   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11001   (((void (**)(void))mat->ops)[op]) = f;
11002   PetscFunctionReturn(PETSC_SUCCESS);
11003 }
11004 
11005 /*@C
11006     MatGetOperation - Gets a matrix operation for any matrix type.
11007 
11008     Not Collective
11009 
11010     Input Parameters:
11011 +   mat - the matrix
11012 -   op - the name of the operation
11013 
11014     Output Parameter:
11015 .   f - the function that provides the operation
11016 
11017     Level: developer
11018 
11019     Usage:
11020 .vb
11021       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11022       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11023 .ve
11024 
11025     Notes:
11026     See the file include/petscmat.h for a complete list of matrix
11027     operations, which all have the form MATOP_<OPERATION>, where
11028     <OPERATION> is the name (in all capital letters) of the
11029     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11030 
11031     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11032 
11033 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11034 @*/
11035 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11036 {
11037   PetscFunctionBegin;
11038   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11039   *f = (((void (**)(void))mat->ops)[op]);
11040   PetscFunctionReturn(PETSC_SUCCESS);
11041 }
11042 
11043 /*@
11044     MatHasOperation - Determines whether the given matrix supports the particular operation.
11045 
11046    Not Collective
11047 
11048    Input Parameters:
11049 +  mat - the matrix
11050 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11051 
11052    Output Parameter:
11053 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11054 
11055    Level: advanced
11056 
11057    Note:
11058    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11059 
11060 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11061 @*/
11062 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11063 {
11064   PetscFunctionBegin;
11065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11066   PetscValidBoolPointer(has, 3);
11067   if (mat->ops->hasoperation) {
11068     PetscUseTypeMethod(mat, hasoperation, op, has);
11069   } else {
11070     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11071     else {
11072       *has = PETSC_FALSE;
11073       if (op == MATOP_CREATE_SUBMATRIX) {
11074         PetscMPIInt size;
11075 
11076         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11077         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11078       }
11079     }
11080   }
11081   PetscFunctionReturn(PETSC_SUCCESS);
11082 }
11083 
11084 /*@
11085     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11086 
11087    Collective
11088 
11089    Input Parameter:
11090 .  mat - the matrix
11091 
11092    Output Parameter:
11093 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11094 
11095    Level: beginner
11096 
11097 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11098 @*/
11099 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11100 {
11101   PetscFunctionBegin;
11102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11103   PetscValidType(mat, 1);
11104   PetscValidBoolPointer(cong, 2);
11105   if (!mat->rmap || !mat->cmap) {
11106     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11107     PetscFunctionReturn(PETSC_SUCCESS);
11108   }
11109   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11110     PetscCall(PetscLayoutSetUp(mat->rmap));
11111     PetscCall(PetscLayoutSetUp(mat->cmap));
11112     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11113     if (*cong) mat->congruentlayouts = 1;
11114     else mat->congruentlayouts = 0;
11115   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11116   PetscFunctionReturn(PETSC_SUCCESS);
11117 }
11118 
11119 PetscErrorCode MatSetInf(Mat A)
11120 {
11121   PetscFunctionBegin;
11122   PetscUseTypeMethod(A, setinf);
11123   PetscFunctionReturn(PETSC_SUCCESS);
11124 }
11125 
11126 /*@C
11127    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
11128    and possibly removes small values from the graph structure.
11129 
11130    Collective
11131 
11132    Input Parameters:
11133 +  A - the matrix
11134 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11135 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11136 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11137 
11138    Output Parameter:
11139 .  graph - the resulting graph
11140 
11141    Level: advanced
11142 
11143 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11144 @*/
11145 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11146 {
11147   PetscFunctionBegin;
11148   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11149   PetscValidType(A, 1);
11150   PetscValidLogicalCollectiveBool(A, scale, 3);
11151   PetscValidPointer(graph, 5);
11152   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11153   PetscFunctionReturn(PETSC_SUCCESS);
11154 }
11155 
11156 /*@
11157   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11158   meaning the same memory is used for the matrix, and no new memory is allocated.
11159 
11160   Collective
11161 
11162   Input Parameter:
11163 . A - the matrix
11164 
11165   Level: intermediate
11166 
11167   Developer Note:
11168   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11169   of the arrays in the data structure are unneeded.
11170 
11171 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11172 @*/
11173 PetscErrorCode MatEliminateZeros(Mat A)
11174 {
11175   PetscFunctionBegin;
11176   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11177   PetscUseTypeMethod(A, eliminatezeros);
11178   PetscFunctionReturn(PETSC_SUCCESS);
11179 }
11180