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