xref: /petsc/src/mat/interface/matrix.c (revision 2d93f1a503e938b95619dbdc11572625ef0cc486) !
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_CUDACopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52    MatSetRandom - Sets all components of a matrix to random numbers.
53 
54    Logically Collective
55 
56    Input Parameters:
57 +  x  - the matrix
58 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61    Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70    Notes:
71    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
72 
73    for sparse matrices that already have locations it fills the locations with random numbers.
74 
75    It generates an error if used on sparse matrices that have not been preallocated.
76 
77 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110    Logically Collective
111 
112    Input Parameter:
113 .  mat - the factored matrix
114 
115    Output Parameters:
116 +  pivot - the pivot value computed
117 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120    Level: advanced
121 
122    Notes:
123     This routine does not work for factorizations done with external packages.
124 
125     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
130           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscValidRealPointer(pivot, 2);
137   PetscValidIntPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144    MatFactorGetError - gets the error code from a factorization
145 
146    Logically Collective
147 
148    Input Parameter:
149 .  mat - the factored matrix
150 
151    Output Parameter:
152 .  err  - the error code
153 
154    Level: advanced
155 
156    Note:
157     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscValidPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172    MatFactorClearError - clears the error code in a factorization
173 
174    Logically Collective
175 
176    Input Parameter:
177 .  mat - the factored matrix
178 
179    Level: developer
180 
181    Note:
182     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 .    A  - the matrix
257 
258   Output Parameter:
259 .    keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264     `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscValidPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282       MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 .    A  - the matrix
286 
287   Output Parameter:
288 .    zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293     `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscValidPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323    Not Collective
324 
325    Input Parameter:
326 .   A - the matrix
327 
328    Output Parameter:
329 .   a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331    Level: advanced
332 
333    Notes:
334    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscValidPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361    Collective
362 
363    Input Parameter:
364 .  mat - the matrix
365 
366    Output Parameter:
367 .   trace - the sum of the diagonal entries
368 
369    Level: advanced
370 
371 .seealso: [](chapter_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscValidScalarPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388    MatRealPart - Zeros out the imaginary part of the matrix
389 
390    Logically Collective
391 
392    Input Parameter:
393 .  mat - the matrix
394 
395    Level: advanced
396 
397 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414    Collective
415 
416    Input Parameter:
417 .  mat - the matrix
418 
419    Output Parameters:
420 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 -   ghosts - the global indices of the ghost points
422 
423    Level: advanced
424 
425    Note:
426    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448    Logically Collective
449 
450    Input Parameter:
451 .  mat - the matrix
452 
453    Level: advanced
454 
455 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472    Not Collective
473 
474    Input Parameter:
475 .  mat - the matrix
476 
477    Output Parameters:
478 +  missing - is any diagonal missing
479 -  dd - first diagonal entry that is missing (optional) on this process
480 
481    Level: advanced
482 
483 .seealso: [](chapter_matrices), `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscValidBoolPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not `NULL`, the number of nonzeros in the row
510 .  cols - if not `NULL`, the column numbers
511 -  vals - if not `NULL`, the values
512 
513    Level: advanced
514 
515    Notes:
516    This routine is provided for people who need to have direct access
517    to the structure of a matrix.  We hope that we provide enough
518    high-level matrix routines that few users will need it.
519 
520    `MatGetRow()` always returns 0-based column indices, regardless of
521    whether the internal representation is 0-based (default) or 1-based.
522 
523    For better efficiency, set cols and/or vals to `NULL` if you do
524    not wish to extract these quantities.
525 
526    The user can only examine the values extracted with `MatGetRow()`;
527    the values cannot be altered.  To change the matrix entries, one
528    must use `MatSetValues()`.
529 
530    You can only have one call to `MatGetRow()` outstanding for a particular
531    matrix at a time, per processor. `MatGetRow()` can only obtain rows
532    associated with the given processor, it cannot get rows from the
533    other processors; for that we suggest using `MatCreateSubMatrices()`, then
534    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535    is in the global number of rows.
536 
537    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541    Fortran Note:
542    The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551    where maxcols >= maximum nonzeros in any row of the matrix.
552 
553    Caution:
554    Do not try to change the contents of the output arrays (`cols` and `vals`).
555    In some cases, this may corrupt the matrix.
556 
557 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   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);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective
581 
582    Input Parameter:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604    Not Collective
605 
606    Input Parameters:
607 +  mat - the matrix
608 .  row - the row to get
609 .  ncols - the number of nonzeros
610 .  cols - the columns of the nonzeros
611 -  vals - if nonzero the column values
612 
613    Level: advanced
614 
615    Notes:
616    This routine should be called after you have finished examining the entries.
617 
618    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619    us of the array after it has been restored. If you pass `NULL`, it will
620    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622    Fortran Notes:
623    The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632    Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635    before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscValidIntPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657    Not Collective
658 
659    Input Parameter:
660 .  mat - the matrix
661 
662    Level: advanced
663 
664    Note:
665    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.
666 
667 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685    Not Collective
686 
687    Input Parameter:
688 .  mat - the matrix
689 
690    Level: advanced
691 
692    Note:
693    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711    MatSetOptionsPrefix - Sets the prefix used for searching for all
712    `Mat` options in the database.
713 
714    Logically Collective
715 
716    Input Parameters:
717 +  A - the matrix
718 -  prefix - the prefix to prepend to all option names
719 
720    Level: advanced
721 
722    Notes:
723    A hyphen (-) must NOT be given at the beginning of the prefix name.
724    The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726    This is NOT used for options for the factorization of the matrix. Normally the
727    prefix is automatically passed in from the PC calling the factorization. To set
728    it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742    for matrices created with `MatGetFactor()`
743 
744    Logically Collective
745 
746    Input Parameters:
747 +  A - the matrix
748 -  prefix - the prefix to prepend to all option names for the factored matrix
749 
750    Level: developer
751 
752    Notes:
753    A hyphen (-) must NOT be given at the beginning of the prefix name.
754    The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](chapter_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscValidCharPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778    for matrices created with `MatGetFactor()`
779 
780    Logically Collective
781 
782    Input Parameters:
783 +  A - the matrix
784 -  prefix - the prefix to prepend to all option names for the factored matrix
785 
786    Level: developer
787 
788    Notes:
789    A hyphen (-) must NOT be given at the beginning of the prefix name.
790    The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822    matrix options in the database.
823 
824    Logically Collective
825 
826    Input Parameters:
827 +  A - the matrix
828 -  prefix - the prefix to prepend to all option names
829 
830    Level: advanced
831 
832    Note:
833    A hyphen (-) must NOT be given at the beginning of the prefix name.
834    The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847    MatGetOptionsPrefix - Gets the prefix used for searching for all
848    matrix options in the database.
849 
850    Not Collective
851 
852    Input Parameter:
853 .  A - the matrix
854 
855    Output Parameter:
856 .  prefix - pointer to the prefix string used
857 
858    Level: advanced
859 
860    Fortran Note:
861    The user should pass in a string `prefix` of
862    sufficient length to hold the prefix.
863 
864 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscValidPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
877 
878    Collective
879 
880    Input Parameter:
881 .  A - the matrix
882 
883    Level: beginner
884 
885    Notes:
886    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888    Users can reset the preallocation to access the original memory.
889 
890    Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
900   PetscFunctionReturn(PETSC_SUCCESS);
901 }
902 
903 /*@
904    MatSetUp - Sets up the internal matrix data structures for later use.
905 
906    Collective
907 
908    Input Parameter:
909 .  A - the matrix
910 
911    Level: intermediate
912 
913    Notes:
914    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
915    setting values in the matrix.
916 
917    If a suitable preallocation routine is used, this function does not need to be called.
918 
919    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*@C
945    MatViewFromOptions - View properties of the matrix based on options set in the options database
946 
947    Collective
948 
949    Input Parameters:
950 +  A - the matrix
951 .  obj - optional additional object that provides the options prefix to use
952 -  name - command line option
953 
954   Options Database Key:
955 .  -mat_view [viewertype]:... - the viewer and its options
956 
957    Level: intermediate
958 
959   Notes:
960 .vb
961     If no value is provided ascii:stdout is used
962        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
963                                                   for example ascii::ascii_info prints just the information about the object not all details
964                                                   unless :append is given filename opens in write mode, overwriting what was already there
965        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
966        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
967        socket[:port]                             defaults to the standard output port
968        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
969 .ve
970 
971 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
972 @*/
973 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
974 {
975   PetscFunctionBegin;
976   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
977   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
978   PetscFunctionReturn(PETSC_SUCCESS);
979 }
980 
981 /*@C
982    MatView - display information about a matrix in a variety ways
983 
984    Collective
985 
986    Input Parameters:
987 +  mat - the matrix
988 -  viewer - visualization context
989 
990    Options Database Keys:
991 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
992 .  -mat_view ::ascii_info_detail - Prints more detailed info
993 .  -mat_view - Prints matrix in ASCII format
994 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
995 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
996 .  -display <name> - Sets display name (default is host)
997 .  -draw_pause <sec> - Sets number of seconds to pause after display
998 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
999 .  -viewer_socket_machine <machine> -
1000 .  -viewer_socket_port <port> -
1001 .  -mat_view binary - save matrix to file in binary format
1002 -  -viewer_binary_filename <name> -
1003 
1004    Level: beginner
1005 
1006   Notes:
1007   The available visualization contexts include
1008 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1009 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1010 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1011 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1012 
1013    The user can open alternative visualization contexts with
1014 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1015 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1016          specified file; corresponding input uses MatLoad()
1017 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1018          an X window display
1019 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1020          Currently only the sequential dense and AIJ
1021          matrix types support the Socket viewer.
1022 
1023    The user can call `PetscViewerPushFormat()` to specify the output
1024    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1025    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1026 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1027 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1028 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1029 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1030          format common among all matrix types
1031 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1032          format (which is in many cases the same as the default)
1033 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1034          size and structure (not the matrix entries)
1035 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1036          the matrix structure
1037 
1038     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1039     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1040 
1041     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1042 
1043     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1044       viewer is used.
1045 
1046       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1047       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1048 
1049       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1050       and then use the following mouse functions.
1051 .vb
1052   left mouse: zoom in
1053   middle mouse: zoom out
1054   right mouse: continue with the simulation
1055 .ve
1056 
1057 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1058           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1059 @*/
1060 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1061 {
1062   PetscInt          rows, cols, rbs, cbs;
1063   PetscBool         isascii, isstring, issaws;
1064   PetscViewerFormat format;
1065   PetscMPIInt       size;
1066 
1067   PetscFunctionBegin;
1068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1069   PetscValidType(mat, 1);
1070   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1071   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1072   PetscCheckSameComm(mat, 1, viewer, 2);
1073 
1074   PetscCall(PetscViewerGetFormat(viewer, &format));
1075   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1076   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1077 
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1080   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1081   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");
1082 
1083   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1084   if (isascii) {
1085     if (!mat->preallocated) {
1086       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1087       PetscFunctionReturn(PETSC_SUCCESS);
1088     }
1089     if (!mat->assembled) {
1090       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1091       PetscFunctionReturn(PETSC_SUCCESS);
1092     }
1093     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1094     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1095       MatNullSpace nullsp, transnullsp;
1096 
1097       PetscCall(PetscViewerASCIIPushTab(viewer));
1098       PetscCall(MatGetSize(mat, &rows, &cols));
1099       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1100       if (rbs != 1 || cbs != 1) {
1101         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1102         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1103       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1104       if (mat->factortype) {
1105         MatSolverType solver;
1106         PetscCall(MatFactorGetSolverType(mat, &solver));
1107         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1108       }
1109       if (mat->ops->getinfo) {
1110         MatInfo info;
1111         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1112         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1113         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1114       }
1115       PetscCall(MatGetNullSpace(mat, &nullsp));
1116       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1117       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1118       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1119       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1120       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatProductView(mat, viewer));
1123       PetscCall(PetscViewerASCIIPopTab(viewer));
1124     }
1125   } else if (issaws) {
1126 #if defined(PETSC_HAVE_SAWS)
1127     PetscMPIInt rank;
1128 
1129     PetscCall(PetscObjectName((PetscObject)mat));
1130     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1131     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1132 #endif
1133   } else if (isstring) {
1134     const char *type;
1135     PetscCall(MatGetType(mat, &type));
1136     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1137     PetscTryTypeMethod(mat, view, viewer);
1138   }
1139   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1140     PetscCall(PetscViewerASCIIPushTab(viewer));
1141     PetscUseTypeMethod(mat, viewnative, viewer);
1142     PetscCall(PetscViewerASCIIPopTab(viewer));
1143   } else if (mat->ops->view) {
1144     PetscCall(PetscViewerASCIIPushTab(viewer));
1145     PetscUseTypeMethod(mat, view, viewer);
1146     PetscCall(PetscViewerASCIIPopTab(viewer));
1147   }
1148   if (isascii) {
1149     PetscCall(PetscViewerGetFormat(viewer, &format));
1150     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1151   }
1152   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1153   PetscFunctionReturn(PETSC_SUCCESS);
1154 }
1155 
1156 #if defined(PETSC_USE_DEBUG)
1157   #include <../src/sys/totalview/tv_data_display.h>
1158 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1159 {
1160   TV_add_row("Local rows", "int", &mat->rmap->n);
1161   TV_add_row("Local columns", "int", &mat->cmap->n);
1162   TV_add_row("Global rows", "int", &mat->rmap->N);
1163   TV_add_row("Global columns", "int", &mat->cmap->N);
1164   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1165   return TV_format_OK;
1166 }
1167 #endif
1168 
1169 /*@C
1170    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1171    with `MatView()`.  The matrix format is determined from the options database.
1172    Generates a parallel MPI matrix if the communicator has more than one
1173    processor.  The default matrix type is `MATAIJ`.
1174 
1175    Collective
1176 
1177    Input Parameters:
1178 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1179             or some related function before a call to `MatLoad()`
1180 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1181 
1182    Options Database Keys:
1183    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1184    block size
1185 .    -matload_block_size <bs> - set block size
1186 
1187    Level: beginner
1188 
1189    Notes:
1190    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1191    `Mat` before calling this routine if you wish to set it from the options database.
1192 
1193    `MatLoad()` automatically loads into the options database any options
1194    given in the file filename.info where filename is the name of the file
1195    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1196    file will be ignored if you use the -viewer_binary_skip_info option.
1197 
1198    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1199    sets the default matrix type AIJ and sets the local and global sizes.
1200    If type and/or size is already set, then the same are used.
1201 
1202    In parallel, each processor can load a subset of rows (or the
1203    entire matrix).  This routine is especially useful when a large
1204    matrix is stored on disk and only part of it is desired on each
1205    processor.  For example, a parallel solver may access only some of
1206    the rows from each processor.  The algorithm used here reads
1207    relatively small blocks of data rather than reading the entire
1208    matrix and then subsetting it.
1209 
1210    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1211    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1212    or the sequence like
1213 .vb
1214     `PetscViewer` v;
1215     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1216     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1217     `PetscViewerSetFromOptions`(v);
1218     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1219     `PetscViewerFileSetName`(v,"datafile");
1220 .ve
1221    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1222 $ -viewer_type {binary,hdf5}
1223 
1224    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1225    and src/mat/tutorials/ex10.c with the second approach.
1226 
1227    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1228    is read onto rank 0 and then shipped to its destination rank, one after another.
1229    Multiple objects, both matrices and vectors, can be stored within the same file.
1230    Their PetscObject name is ignored; they are loaded in the order of their storage.
1231 
1232    Most users should not need to know the details of the binary storage
1233    format, since `MatLoad()` and `MatView()` completely hide these details.
1234    But for anyone who's interested, the standard binary matrix storage
1235    format is
1236 
1237 .vb
1238     PetscInt    MAT_FILE_CLASSID
1239     PetscInt    number of rows
1240     PetscInt    number of columns
1241     PetscInt    total number of nonzeros
1242     PetscInt    *number nonzeros in each row
1243     PetscInt    *column indices of all nonzeros (starting index is zero)
1244     PetscScalar *values of all nonzeros
1245 .ve
1246 
1247    PETSc automatically does the byte swapping for
1248 machines that store the bytes reversed. Thus if you write your own binary
1249 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1250 and `PetscBinaryWrite()` to see how this may be done.
1251 
1252    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1253    Each processor's chunk is loaded independently by its owning rank.
1254    Multiple objects, both matrices and vectors, can be stored within the same file.
1255    They are looked up by their PetscObject name.
1256 
1257    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1258    by default the same structure and naming of the AIJ arrays and column count
1259    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1260 $    save example.mat A b -v7.3
1261    can be directly read by this routine (see Reference 1 for details).
1262 
1263    Depending on your MATLAB version, this format might be a default,
1264    otherwise you can set it as default in Preferences.
1265 
1266    Unless -nocompression flag is used to save the file in MATLAB,
1267    PETSc must be configured with ZLIB package.
1268 
1269    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1270 
1271    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1272 
1273    Corresponding `MatView()` is not yet implemented.
1274 
1275    The loaded matrix is actually a transpose of the original one in MATLAB,
1276    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1277    With this format, matrix is automatically transposed by PETSc,
1278    unless the matrix is marked as SPD or symmetric
1279    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1280 
1281    References:
1282 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1283 
1284 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1285  @*/
1286 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1287 {
1288   PetscBool flg;
1289 
1290   PetscFunctionBegin;
1291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1292   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1293 
1294   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1295 
1296   flg = PETSC_FALSE;
1297   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1298   if (flg) {
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1300     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1301   }
1302   flg = PETSC_FALSE;
1303   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1304   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1305 
1306   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1307   PetscUseTypeMethod(mat, load, viewer);
1308   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1309   PetscFunctionReturn(PETSC_SUCCESS);
1310 }
1311 
1312 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1313 {
1314   Mat_Redundant *redund = *redundant;
1315 
1316   PetscFunctionBegin;
1317   if (redund) {
1318     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1319       PetscCall(ISDestroy(&redund->isrow));
1320       PetscCall(ISDestroy(&redund->iscol));
1321       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1322     } else {
1323       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1324       PetscCall(PetscFree(redund->sbuf_j));
1325       PetscCall(PetscFree(redund->sbuf_a));
1326       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1327         PetscCall(PetscFree(redund->rbuf_j[i]));
1328         PetscCall(PetscFree(redund->rbuf_a[i]));
1329       }
1330       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1331     }
1332 
1333     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1334     PetscCall(PetscFree(redund));
1335   }
1336   PetscFunctionReturn(PETSC_SUCCESS);
1337 }
1338 
1339 /*@C
1340    MatDestroy - Frees space taken by a matrix.
1341 
1342    Collective
1343 
1344    Input Parameter:
1345 .  A - the matrix
1346 
1347    Level: beginner
1348 
1349    Developer Note:
1350    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1351    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1352    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1353    if changes are needed here.
1354 
1355 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1356 @*/
1357 PetscErrorCode MatDestroy(Mat *A)
1358 {
1359   PetscFunctionBegin;
1360   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1361   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1362   if (--((PetscObject)(*A))->refct > 0) {
1363     *A = NULL;
1364     PetscFunctionReturn(PETSC_SUCCESS);
1365   }
1366 
1367   /* if memory was published with SAWs then destroy it */
1368   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1369   PetscTryTypeMethod((*A), destroy);
1370 
1371   PetscCall(PetscFree((*A)->factorprefix));
1372   PetscCall(PetscFree((*A)->defaultvectype));
1373   PetscCall(PetscFree((*A)->defaultrandtype));
1374   PetscCall(PetscFree((*A)->bsizes));
1375   PetscCall(PetscFree((*A)->solvertype));
1376   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1377   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1378   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1379   PetscCall(MatProductClear(*A));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1382   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1383   PetscCall(MatDestroy(&(*A)->schur));
1384   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1385   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1386   PetscCall(PetscHeaderDestroy(A));
1387   PetscFunctionReturn(PETSC_SUCCESS);
1388 }
1389 
1390 /*@C
1391    MatSetValues - Inserts or adds a block of values into a matrix.
1392    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1393    MUST be called after all calls to `MatSetValues()` have been completed.
1394 
1395    Not Collective
1396 
1397    Input Parameters:
1398 +  mat - the matrix
1399 .  v - a logically two-dimensional array of values
1400 .  m - the number of rows
1401 .  idxm - the global indices of the rows
1402 .  n - the number of columns
1403 .  idxn - the global indices of the columns
1404 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1405 
1406    Level: beginner
1407 
1408    Notes:
1409    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1410 
1411    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1412    options cannot be mixed without intervening calls to the assembly
1413    routines.
1414 
1415    `MatSetValues()` uses 0-based row and column numbers in Fortran
1416    as well as in C.
1417 
1418    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1419    simply ignored. This allows easily inserting element stiffness matrices
1420    with homogeneous Dirchlet boundary conditions that you don't want represented
1421    in the matrix.
1422 
1423    Efficiency Alert:
1424    The routine `MatSetValuesBlocked()` may offer much better efficiency
1425    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1426 
1427    Developer Note:
1428    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1429    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1430 
1431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1432           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1433 @*/
1434 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1435 {
1436   PetscFunctionBeginHot;
1437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1438   PetscValidType(mat, 1);
1439   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1440   PetscValidIntPointer(idxm, 3);
1441   PetscValidIntPointer(idxn, 5);
1442   MatCheckPreallocated(mat, 1);
1443 
1444   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1445   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1446 
1447   if (PetscDefined(USE_DEBUG)) {
1448     PetscInt i, j;
1449 
1450     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1451     for (i = 0; i < m; i++) {
1452       for (j = 0; j < n; j++) {
1453         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1454 #if defined(PETSC_USE_COMPLEX)
1455           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]);
1456 #else
1457           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]);
1458 #endif
1459       }
1460     }
1461     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);
1462     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);
1463   }
1464 
1465   if (mat->assembled) {
1466     mat->was_assembled = PETSC_TRUE;
1467     mat->assembled     = PETSC_FALSE;
1468   }
1469   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1470   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1471   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1472   PetscFunctionReturn(PETSC_SUCCESS);
1473 }
1474 
1475 /*@C
1476    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1477    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1478    MUST be called after all calls to `MatSetValues()` have been completed.
1479 
1480    Not Collective
1481 
1482    Input Parameters:
1483 +  mat - the matrix
1484 .  v - a logically two-dimensional array of values
1485 .  ism - the rows to provide
1486 .  isn - the columns to provide
1487 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1488 
1489    Level: beginner
1490 
1491    Notes:
1492    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1493 
1494    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1495    options cannot be mixed without intervening calls to the assembly
1496    routines.
1497 
1498    `MatSetValues()` uses 0-based row and column numbers in Fortran
1499    as well as in C.
1500 
1501    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1502    simply ignored. This allows easily inserting element stiffness matrices
1503    with homogeneous Dirchlet boundary conditions that you don't want represented
1504    in the matrix.
1505 
1506    Efficiency Alert:
1507    The routine `MatSetValuesBlocked()` may offer much better efficiency
1508    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1509 
1510     This is currently not optimized for any particular `ISType`
1511 
1512    Developer Notes:
1513     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1514                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1515 
1516 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1517           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1518 @*/
1519 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1520 {
1521   PetscInt        m, n;
1522   const PetscInt *rows, *cols;
1523 
1524   PetscFunctionBeginHot;
1525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1526   PetscCall(ISGetIndices(ism, &rows));
1527   PetscCall(ISGetIndices(isn, &cols));
1528   PetscCall(ISGetLocalSize(ism, &m));
1529   PetscCall(ISGetLocalSize(isn, &n));
1530   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1531   PetscCall(ISRestoreIndices(ism, &rows));
1532   PetscCall(ISRestoreIndices(isn, &cols));
1533   PetscFunctionReturn(PETSC_SUCCESS);
1534 }
1535 
1536 /*@
1537    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1538         values into a matrix
1539 
1540    Not Collective
1541 
1542    Input Parameters:
1543 +  mat - the matrix
1544 .  row - the (block) row to set
1545 -  v - a logically two-dimensional array of values
1546 
1547    Level: intermediate
1548 
1549    Notes:
1550    The values, `v`, are column-oriented (for the block version) and sorted
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    The matrix must have previously had its column indices set, likely by having been assembled.
1555 
1556    The row must belong to this process
1557 
1558 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1560 @*/
1561 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1562 {
1563   PetscInt globalrow;
1564 
1565   PetscFunctionBegin;
1566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1567   PetscValidType(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1570   PetscCall(MatSetValuesRow(mat, globalrow, v));
1571   PetscFunctionReturn(PETSC_SUCCESS);
1572 }
1573 
1574 /*@
1575    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1576         values into a matrix
1577 
1578    Not Collective
1579 
1580    Input Parameters:
1581 +  mat - the matrix
1582 .  row - the (block) row to set
1583 -  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
1584 
1585    Level: advanced
1586 
1587    Notes:
1588    The values, `v`, are column-oriented for the block version.
1589 
1590    All the nonzeros in the row must be provided
1591 
1592    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1593 
1594    The row must belong to this process
1595 
1596 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1597           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1598 @*/
1599 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1600 {
1601   PetscFunctionBeginHot;
1602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1603   PetscValidType(mat, 1);
1604   MatCheckPreallocated(mat, 1);
1605   PetscValidScalarPointer(v, 3);
1606   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1607   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1608   mat->insertmode = INSERT_VALUES;
1609 
1610   if (mat->assembled) {
1611     mat->was_assembled = PETSC_TRUE;
1612     mat->assembled     = PETSC_FALSE;
1613   }
1614   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1615   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1616   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1617   PetscFunctionReturn(PETSC_SUCCESS);
1618 }
1619 
1620 /*@
1621    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1622      Using structured grid indexing
1623 
1624    Not Collective
1625 
1626    Input Parameters:
1627 +  mat - the matrix
1628 .  m - number of rows being entered
1629 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1630 .  n - number of columns being entered
1631 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1632 .  v - a logically two-dimensional array of values
1633 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1634 
1635    Level: beginner
1636 
1637    Notes:
1638    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1639 
1640    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1641    options cannot be mixed without intervening calls to the assembly
1642    routines.
1643 
1644    The grid coordinates are across the entire grid, not just the local portion
1645 
1646    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1647    as well as in C.
1648 
1649    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1650 
1651    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1652    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1653 
1654    The columns and rows in the stencil passed in MUST be contained within the
1655    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1656    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1657    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1658    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1659 
1660    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1661    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1662    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1663    `DM_BOUNDARY_PERIODIC` boundary type.
1664 
1665    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
1666    a single value per point) you can skip filling those indices.
1667 
1668    Inspired by the structured grid interface to the HYPRE package
1669    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1670 
1671    Efficiency Alert:
1672    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1673    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1674 
1675    Fortran Note:
1676    `idxm` and `idxn` should be declared as
1677 $     MatStencil idxm(4,m),idxn(4,n)
1678    and the values inserted using
1679 .vb
1680     idxm(MatStencil_i,1) = i
1681     idxm(MatStencil_j,1) = j
1682     idxm(MatStencil_k,1) = k
1683     idxm(MatStencil_c,1) = c
1684     etc
1685 .ve
1686 
1687 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1688           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1689 @*/
1690 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1691 {
1692   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1693   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1694   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1695 
1696   PetscFunctionBegin;
1697   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1699   PetscValidType(mat, 1);
1700   PetscValidPointer(idxm, 3);
1701   PetscValidPointer(idxn, 5);
1702 
1703   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1704     jdxm = buf;
1705     jdxn = buf + m;
1706   } else {
1707     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1708     jdxm = bufm;
1709     jdxn = bufn;
1710   }
1711   for (i = 0; i < m; i++) {
1712     for (j = 0; j < 3 - sdim; j++) dxm++;
1713     tmp = *dxm++ - starts[0];
1714     for (j = 0; j < dim - 1; j++) {
1715       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1716       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1717     }
1718     if (mat->stencil.noc) dxm++;
1719     jdxm[i] = tmp;
1720   }
1721   for (i = 0; i < n; i++) {
1722     for (j = 0; j < 3 - sdim; j++) dxn++;
1723     tmp = *dxn++ - starts[0];
1724     for (j = 0; j < dim - 1; j++) {
1725       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1726       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1727     }
1728     if (mat->stencil.noc) dxn++;
1729     jdxn[i] = tmp;
1730   }
1731   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1732   PetscCall(PetscFree2(bufm, bufn));
1733   PetscFunctionReturn(PETSC_SUCCESS);
1734 }
1735 
1736 /*@
1737    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1738      Using structured grid indexing
1739 
1740    Not Collective
1741 
1742    Input Parameters:
1743 +  mat - the matrix
1744 .  m - number of rows being entered
1745 .  idxm - grid coordinates for matrix rows being entered
1746 .  n - number of columns being entered
1747 .  idxn - grid coordinates for matrix columns being entered
1748 .  v - a logically two-dimensional array of values
1749 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1750 
1751    Level: beginner
1752 
1753    Notes:
1754    By default the values, `v`, are row-oriented and unsorted.
1755    See `MatSetOption()` for other options.
1756 
1757    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1758    options cannot be mixed without intervening calls to the assembly
1759    routines.
1760 
1761    The grid coordinates are across the entire grid, not just the local portion
1762 
1763    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1764    as well as in C.
1765 
1766    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1767 
1768    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1769    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1770 
1771    The columns and rows in the stencil passed in MUST be contained within the
1772    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1773    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1774    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1775    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1776 
1777    Negative indices may be passed in idxm and idxn, these rows and columns are
1778    simply ignored. This allows easily inserting element stiffness matrices
1779    with homogeneous Dirchlet boundary conditions that you don't want represented
1780    in the matrix.
1781 
1782    Inspired by the structured grid interface to the HYPRE package
1783    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1784 
1785    Fortran Note:
1786    `idxm` and `idxn` should be declared as
1787 $     MatStencil idxm(4,m),idxn(4,n)
1788    and the values inserted using
1789 .vb
1790     idxm(MatStencil_i,1) = i
1791     idxm(MatStencil_j,1) = j
1792     idxm(MatStencil_k,1) = k
1793    etc
1794 .ve
1795 
1796 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1797           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1798           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1799 @*/
1800 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1801 {
1802   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1803   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1804   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1805 
1806   PetscFunctionBegin;
1807   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1809   PetscValidType(mat, 1);
1810   PetscValidPointer(idxm, 3);
1811   PetscValidPointer(idxn, 5);
1812   PetscValidScalarPointer(v, 6);
1813 
1814   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1815     jdxm = buf;
1816     jdxn = buf + m;
1817   } else {
1818     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1819     jdxm = bufm;
1820     jdxn = bufn;
1821   }
1822   for (i = 0; i < m; i++) {
1823     for (j = 0; j < 3 - sdim; j++) dxm++;
1824     tmp = *dxm++ - starts[0];
1825     for (j = 0; j < sdim - 1; j++) {
1826       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1827       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1828     }
1829     dxm++;
1830     jdxm[i] = tmp;
1831   }
1832   for (i = 0; i < n; i++) {
1833     for (j = 0; j < 3 - sdim; j++) dxn++;
1834     tmp = *dxn++ - starts[0];
1835     for (j = 0; j < sdim - 1; j++) {
1836       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1837       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1838     }
1839     dxn++;
1840     jdxn[i] = tmp;
1841   }
1842   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1843   PetscCall(PetscFree2(bufm, bufn));
1844   PetscFunctionReturn(PETSC_SUCCESS);
1845 }
1846 
1847 /*@
1848    MatSetStencil - Sets the grid information for setting values into a matrix via
1849         `MatSetValuesStencil()`
1850 
1851    Not Collective
1852 
1853    Input Parameters:
1854 +  mat - the matrix
1855 .  dim - dimension of the grid 1, 2, or 3
1856 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1857 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1858 -  dof - number of degrees of freedom per node
1859 
1860    Level: beginner
1861 
1862    Notes:
1863    Inspired by the structured grid interface to the HYPRE package
1864    (www.llnl.gov/CASC/hyper)
1865 
1866    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1867    user.
1868 
1869 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1870           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1871 @*/
1872 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1873 {
1874   PetscFunctionBegin;
1875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1876   PetscValidIntPointer(dims, 3);
1877   PetscValidIntPointer(starts, 4);
1878 
1879   mat->stencil.dim = dim + (dof > 1);
1880   for (PetscInt i = 0; i < dim; i++) {
1881     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1882     mat->stencil.starts[i] = starts[dim - i - 1];
1883   }
1884   mat->stencil.dims[dim]   = dof;
1885   mat->stencil.starts[dim] = 0;
1886   mat->stencil.noc         = (PetscBool)(dof == 1);
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@C
1891    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1892 
1893    Not Collective
1894 
1895    Input Parameters:
1896 +  mat - the matrix
1897 .  v - a logically two-dimensional array of values
1898 .  m  - the number of block rows
1899 .  idxm - the global block indices
1900 .  n - the number of block columns
1901 .  idxn - the global block indices
1902 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1903 
1904    Level: intermediate
1905 
1906    Notes:
1907    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1908    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1909 
1910    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1911    NOT the total number of rows/columns; for example, if the block size is 2 and
1912    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1913    The values in idxm would be 1 2; that is the first index for each block divided by
1914    the block size.
1915 
1916    You must call `MatSetBlockSize()` when constructing this matrix (before
1917    preallocating it).
1918 
1919    By default the values, `v`, are row-oriented, so the layout of
1920    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1921 
1922    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1923    options cannot be mixed without intervening calls to the assembly
1924    routines.
1925 
1926    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1927    as well as in C.
1928 
1929    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1930    simply ignored. This allows easily inserting element stiffness matrices
1931    with homogeneous Dirchlet boundary conditions that you don't want represented
1932    in the matrix.
1933 
1934    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1935    internal searching must be done to determine where to place the
1936    data in the matrix storage space.  By instead inserting blocks of
1937    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1938    reduced.
1939 
1940    Example:
1941 .vb
1942    Suppose m=n=2 and block size(bs) = 2 The array is
1943 
1944    1  2  | 3  4
1945    5  6  | 7  8
1946    - - - | - - -
1947    9  10 | 11 12
1948    13 14 | 15 16
1949 
1950    v[] should be passed in like
1951    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1952 
1953   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1954    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1955 .ve
1956 
1957 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1958 @*/
1959 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1960 {
1961   PetscFunctionBeginHot;
1962   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1963   PetscValidType(mat, 1);
1964   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1965   PetscValidIntPointer(idxm, 3);
1966   PetscValidIntPointer(idxn, 5);
1967   MatCheckPreallocated(mat, 1);
1968   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1969   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1970   if (PetscDefined(USE_DEBUG)) {
1971     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1972     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1973   }
1974   if (PetscDefined(USE_DEBUG)) {
1975     PetscInt rbs, cbs, M, N, i;
1976     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1977     PetscCall(MatGetSize(mat, &M, &N));
1978     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);
1979     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);
1980   }
1981   if (mat->assembled) {
1982     mat->was_assembled = PETSC_TRUE;
1983     mat->assembled     = PETSC_FALSE;
1984   }
1985   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1986   if (mat->ops->setvaluesblocked) {
1987     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1988   } else {
1989     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1990     PetscInt i, j, bs, cbs;
1991 
1992     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1993     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1994       iidxm = buf;
1995       iidxn = buf + m * bs;
1996     } else {
1997       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1998       iidxm = bufr;
1999       iidxn = bufc;
2000     }
2001     for (i = 0; i < m; i++) {
2002       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2003     }
2004     if (m != n || bs != cbs || idxm != idxn) {
2005       for (i = 0; i < n; i++) {
2006         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2007       }
2008     } else iidxn = iidxm;
2009     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2010     PetscCall(PetscFree2(bufr, bufc));
2011   }
2012   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2013   PetscFunctionReturn(PETSC_SUCCESS);
2014 }
2015 
2016 /*@C
2017    MatGetValues - Gets a block of local values from a matrix.
2018 
2019    Not Collective; can only return values that are owned by the give process
2020 
2021    Input Parameters:
2022 +  mat - the matrix
2023 .  v - a logically two-dimensional array for storing the values
2024 .  m  - the number of rows
2025 .  idxm - the  global indices of the rows
2026 .  n - the number of columns
2027 -  idxn - the global indices of the columns
2028 
2029    Level: advanced
2030 
2031    Notes:
2032      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2033      The values, `v`, are then returned in a row-oriented format,
2034      analogous to that used by default in `MatSetValues()`.
2035 
2036      `MatGetValues()` uses 0-based row and column numbers in
2037      Fortran as well as in C.
2038 
2039      `MatGetValues()` requires that the matrix has been assembled
2040      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2041      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2042      without intermediate matrix assembly.
2043 
2044      Negative row or column indices will be ignored and those locations in `v` will be
2045      left unchanged.
2046 
2047      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2048      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2049      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2050 
2051 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2052 @*/
2053 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2054 {
2055   PetscFunctionBegin;
2056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2057   PetscValidType(mat, 1);
2058   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2059   PetscValidIntPointer(idxm, 3);
2060   PetscValidIntPointer(idxn, 5);
2061   PetscValidScalarPointer(v, 6);
2062   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2063   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2064   MatCheckPreallocated(mat, 1);
2065 
2066   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2067   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2068   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2069   PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 
2072 /*@C
2073    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2074      defined previously by `MatSetLocalToGlobalMapping()`
2075 
2076    Not Collective
2077 
2078    Input Parameters:
2079 +  mat - the matrix
2080 .  nrow - number of rows
2081 .  irow - the row local indices
2082 .  ncol - number of columns
2083 -  icol - the column local indices
2084 
2085    Output Parameter:
2086 .  y -  a logically two-dimensional array of values
2087 
2088    Level: advanced
2089 
2090    Notes:
2091      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2092 
2093      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,
2094      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2095      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2096      with `MatSetLocalToGlobalMapping()`.
2097 
2098    Developer Note:
2099       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2100       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2101 
2102 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2103           `MatSetValuesLocal()`, `MatGetValues()`
2104 @*/
2105 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2106 {
2107   PetscFunctionBeginHot;
2108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2109   PetscValidType(mat, 1);
2110   MatCheckPreallocated(mat, 1);
2111   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2112   PetscValidIntPointer(irow, 3);
2113   PetscValidIntPointer(icol, 5);
2114   if (PetscDefined(USE_DEBUG)) {
2115     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2116     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2117   }
2118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2119   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2120   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2121   else {
2122     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2123     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2124       irowm = buf;
2125       icolm = buf + nrow;
2126     } else {
2127       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2128       irowm = bufr;
2129       icolm = bufc;
2130     }
2131     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2133     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2134     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2135     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2136     PetscCall(PetscFree2(bufr, bufc));
2137   }
2138   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2139   PetscFunctionReturn(PETSC_SUCCESS);
2140 }
2141 
2142 /*@
2143   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2144   the same size. Currently, this can only be called once and creates the given matrix.
2145 
2146   Not Collective
2147 
2148   Input Parameters:
2149 + mat - the matrix
2150 . nb - the number of blocks
2151 . bs - the number of rows (and columns) in each block
2152 . rows - a concatenation of the rows for each block
2153 - v - a concatenation of logically two-dimensional arrays of values
2154 
2155   Level: advanced
2156 
2157   Note:
2158   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2159 
2160   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2161 
2162 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2163           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2164 @*/
2165 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2166 {
2167   PetscFunctionBegin;
2168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2169   PetscValidType(mat, 1);
2170   PetscValidIntPointer(rows, 4);
2171   PetscValidScalarPointer(v, 5);
2172   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2173 
2174   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2175   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2176   else {
2177     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2178   }
2179   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@
2184    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2185    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2186    using a local (per-processor) numbering.
2187 
2188    Not Collective
2189 
2190    Input Parameters:
2191 +  x - the matrix
2192 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2193 -  cmapping - column mapping
2194 
2195    Level: intermediate
2196 
2197    Note:
2198    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2199 
2200 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2201 @*/
2202 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2203 {
2204   PetscFunctionBegin;
2205   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2206   PetscValidType(x, 1);
2207   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2208   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2209   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2210   else {
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2212     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2213   }
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@
2218    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2219 
2220    Not Collective
2221 
2222    Input Parameter:
2223 .  A - the matrix
2224 
2225    Output Parameters:
2226 + rmapping - row mapping
2227 - cmapping - column mapping
2228 
2229    Level: advanced
2230 
2231 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2237   PetscValidType(A, 1);
2238   if (rmapping) {
2239     PetscValidPointer(rmapping, 2);
2240     *rmapping = A->rmap->mapping;
2241   }
2242   if (cmapping) {
2243     PetscValidPointer(cmapping, 3);
2244     *cmapping = A->cmap->mapping;
2245   }
2246   PetscFunctionReturn(PETSC_SUCCESS);
2247 }
2248 
2249 /*@
2250    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2251 
2252    Logically Collective
2253 
2254    Input Parameters:
2255 +  A - the matrix
2256 . rmap - row layout
2257 - cmap - column layout
2258 
2259    Level: advanced
2260 
2261    Note:
2262    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2263 
2264 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2265 @*/
2266 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2267 {
2268   PetscFunctionBegin;
2269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2270   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2271   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2272   PetscFunctionReturn(PETSC_SUCCESS);
2273 }
2274 
2275 /*@
2276    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2277 
2278    Not Collective
2279 
2280    Input Parameter:
2281 .  A - the matrix
2282 
2283    Output Parameters:
2284 + rmap - row layout
2285 - cmap - column layout
2286 
2287    Level: advanced
2288 
2289 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2290 @*/
2291 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2292 {
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2295   PetscValidType(A, 1);
2296   if (rmap) {
2297     PetscValidPointer(rmap, 2);
2298     *rmap = A->rmap;
2299   }
2300   if (cmap) {
2301     PetscValidPointer(cmap, 3);
2302     *cmap = A->cmap;
2303   }
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@C
2308    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2309    using a local numbering of the nodes.
2310 
2311    Not Collective
2312 
2313    Input Parameters:
2314 +  mat - the matrix
2315 .  nrow - number of rows
2316 .  irow - the row local indices
2317 .  ncol - number of columns
2318 .  icol - the column local indices
2319 .  y -  a logically two-dimensional array of values
2320 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2321 
2322    Level: intermediate
2323 
2324    Notes:
2325    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2326       `MatSetUp()` before using this routine
2327 
2328    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2329 
2330    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2331    options cannot be mixed without intervening calls to the assembly
2332    routines.
2333 
2334    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2335    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2336 
2337    Developer Note:
2338     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2339                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2340 
2341 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2342           `MatGetValuesLocal()`
2343 @*/
2344 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2345 {
2346   PetscFunctionBeginHot;
2347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2348   PetscValidType(mat, 1);
2349   MatCheckPreallocated(mat, 1);
2350   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2351   PetscValidIntPointer(irow, 3);
2352   PetscValidIntPointer(icol, 5);
2353   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2354   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2355   if (PetscDefined(USE_DEBUG)) {
2356     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2357     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2358   }
2359 
2360   if (mat->assembled) {
2361     mat->was_assembled = PETSC_TRUE;
2362     mat->assembled     = PETSC_FALSE;
2363   }
2364   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2365   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2366   else {
2367     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2368     const PetscInt *irowm, *icolm;
2369 
2370     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2371       bufr  = buf;
2372       bufc  = buf + nrow;
2373       irowm = bufr;
2374       icolm = bufc;
2375     } else {
2376       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2377       irowm = bufr;
2378       icolm = bufc;
2379     }
2380     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2381     else irowm = irow;
2382     if (mat->cmap->mapping) {
2383       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2384         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2385       } else icolm = irowm;
2386     } else icolm = icol;
2387     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2388     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2389   }
2390   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2391   PetscFunctionReturn(PETSC_SUCCESS);
2392 }
2393 
2394 /*@C
2395    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2396    using a local ordering of the nodes a block at a time.
2397 
2398    Not Collective
2399 
2400    Input Parameters:
2401 +  x - the matrix
2402 .  nrow - number of rows
2403 .  irow - the row local indices
2404 .  ncol - number of columns
2405 .  icol - the column local indices
2406 .  y -  a logically two-dimensional array of values
2407 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2408 
2409    Level: intermediate
2410 
2411    Notes:
2412    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2413       `MatSetUp()` before using this routine
2414 
2415    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2416       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2417 
2418    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2419    options cannot be mixed without intervening calls to the assembly
2420    routines.
2421 
2422    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2423    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2424 
2425    Developer Note:
2426     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2427                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2428 
2429 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2430           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2431 @*/
2432 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2433 {
2434   PetscFunctionBeginHot;
2435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2436   PetscValidType(mat, 1);
2437   MatCheckPreallocated(mat, 1);
2438   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2439   PetscValidIntPointer(irow, 3);
2440   PetscValidIntPointer(icol, 5);
2441   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2442   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2443   if (PetscDefined(USE_DEBUG)) {
2444     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2445     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);
2446   }
2447 
2448   if (mat->assembled) {
2449     mat->was_assembled = PETSC_TRUE;
2450     mat->assembled     = PETSC_FALSE;
2451   }
2452   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2453     PetscInt irbs, rbs;
2454     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2455     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2456     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2457   }
2458   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2459     PetscInt icbs, cbs;
2460     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2461     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2462     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2463   }
2464   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2465   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2466   else {
2467     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2468     const PetscInt *irowm, *icolm;
2469 
2470     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2471       bufr  = buf;
2472       bufc  = buf + nrow;
2473       irowm = bufr;
2474       icolm = bufc;
2475     } else {
2476       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2477       irowm = bufr;
2478       icolm = bufc;
2479     }
2480     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2481     else irowm = irow;
2482     if (mat->cmap->mapping) {
2483       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2484         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2485       } else icolm = irowm;
2486     } else icolm = icol;
2487     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2488     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2489   }
2490   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2491   PetscFunctionReturn(PETSC_SUCCESS);
2492 }
2493 
2494 /*@
2495    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2496 
2497    Collective
2498 
2499    Input Parameters:
2500 +  mat - the matrix
2501 -  x   - the vector to be multiplied
2502 
2503    Output Parameter:
2504 .  y - the result
2505 
2506    Level: developer
2507 
2508    Note:
2509    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2510    call `MatMultDiagonalBlock`(A,y,y).
2511 
2512 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2513 @*/
2514 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2515 {
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2518   PetscValidType(mat, 1);
2519   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2520   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2521 
2522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2524   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2525   MatCheckPreallocated(mat, 1);
2526 
2527   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2528   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2529   PetscFunctionReturn(PETSC_SUCCESS);
2530 }
2531 
2532 /*@
2533    MatMult - Computes the matrix-vector product, y = Ax.
2534 
2535    Neighbor-wise Collective
2536 
2537    Input Parameters:
2538 +  mat - the matrix
2539 -  x   - the vector to be multiplied
2540 
2541    Output Parameter:
2542 .  y - the result
2543 
2544    Level: beginner
2545 
2546    Note:
2547    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2548    call `MatMult`(A,y,y).
2549 
2550 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2551 @*/
2552 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2553 {
2554   PetscFunctionBegin;
2555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2556   PetscValidType(mat, 1);
2557   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2558   VecCheckAssembled(x);
2559   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2560   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2561   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2562   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2563   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);
2564   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);
2565   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);
2566   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);
2567   PetscCall(VecSetErrorIfLocked(y, 3));
2568   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2569   MatCheckPreallocated(mat, 1);
2570 
2571   PetscCall(VecLockReadPush(x));
2572   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2573   PetscUseTypeMethod(mat, mult, x, y);
2574   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2575   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2576   PetscCall(VecLockReadPop(x));
2577   PetscFunctionReturn(PETSC_SUCCESS);
2578 }
2579 
2580 /*@
2581    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2582 
2583    Neighbor-wise Collective
2584 
2585    Input Parameters:
2586 +  mat - the matrix
2587 -  x   - the vector to be multiplied
2588 
2589    Output Parameter:
2590 .  y - the result
2591 
2592    Level: beginner
2593 
2594    Notes:
2595    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2596    call `MatMultTranspose`(A,y,y).
2597 
2598    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2599    use `MatMultHermitianTranspose()`
2600 
2601 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2602 @*/
2603 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2604 {
2605   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2606 
2607   PetscFunctionBegin;
2608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2609   PetscValidType(mat, 1);
2610   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2611   VecCheckAssembled(x);
2612   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2613 
2614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2616   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2617   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);
2618   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);
2619   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);
2620   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);
2621   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2622   MatCheckPreallocated(mat, 1);
2623 
2624   if (!mat->ops->multtranspose) {
2625     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2626     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);
2627   } else op = mat->ops->multtranspose;
2628   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2629   PetscCall(VecLockReadPush(x));
2630   PetscCall((*op)(mat, x, y));
2631   PetscCall(VecLockReadPop(x));
2632   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2633   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2634   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2635   PetscFunctionReturn(PETSC_SUCCESS);
2636 }
2637 
2638 /*@
2639    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2640 
2641    Neighbor-wise Collective
2642 
2643    Input Parameters:
2644 +  mat - the matrix
2645 -  x   - the vector to be multilplied
2646 
2647    Output Parameter:
2648 .  y - the result
2649 
2650    Level: beginner
2651 
2652    Notes:
2653    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2654    call `MatMultHermitianTranspose`(A,y,y).
2655 
2656    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2657 
2658    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2659 
2660 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2661 @*/
2662 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2663 {
2664   PetscFunctionBegin;
2665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2666   PetscValidType(mat, 1);
2667   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2668   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2669 
2670   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2671   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2672   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2673   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);
2674   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);
2675   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);
2676   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);
2677   MatCheckPreallocated(mat, 1);
2678 
2679   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2680 #if defined(PETSC_USE_COMPLEX)
2681   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2682     PetscCall(VecLockReadPush(x));
2683     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2684     else PetscUseTypeMethod(mat, mult, x, y);
2685     PetscCall(VecLockReadPop(x));
2686   } else {
2687     Vec w;
2688     PetscCall(VecDuplicate(x, &w));
2689     PetscCall(VecCopy(x, w));
2690     PetscCall(VecConjugate(w));
2691     PetscCall(MatMultTranspose(mat, w, y));
2692     PetscCall(VecDestroy(&w));
2693     PetscCall(VecConjugate(y));
2694   }
2695   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2696 #else
2697   PetscCall(MatMultTranspose(mat, x, y));
2698 #endif
2699   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2700   PetscFunctionReturn(PETSC_SUCCESS);
2701 }
2702 
2703 /*@
2704     MatMultAdd -  Computes v3 = v2 + A * v1.
2705 
2706     Neighbor-wise Collective
2707 
2708     Input Parameters:
2709 +   mat - the matrix
2710 .   v1 - the vector to be multiplied by `mat`
2711 -   v2 - the vector to be added to the result
2712 
2713     Output Parameter:
2714 .   v3 - the result
2715 
2716     Level: beginner
2717 
2718     Note:
2719     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2720     call `MatMultAdd`(A,v1,v2,v1).
2721 
2722 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2723 @*/
2724 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2725 {
2726   PetscFunctionBegin;
2727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2728   PetscValidType(mat, 1);
2729   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2730   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2731   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2732 
2733   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2735   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);
2736   /* 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);
2737      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); */
2738   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);
2739   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);
2740   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2741   MatCheckPreallocated(mat, 1);
2742 
2743   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2744   PetscCall(VecLockReadPush(v1));
2745   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2746   PetscCall(VecLockReadPop(v1));
2747   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2748   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 /*@
2753    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2754 
2755    Neighbor-wise Collective
2756 
2757    Input Parameters:
2758 +  mat - the matrix
2759 .  v1 - the vector to be multiplied by the transpose of the matrix
2760 -  v2 - the vector to be added to the result
2761 
2762    Output Parameter:
2763 .  v3 - the result
2764 
2765    Level: beginner
2766 
2767    Note:
2768    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2769    call `MatMultTransposeAdd`(A,v1,v2,v1).
2770 
2771 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2772 @*/
2773 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2774 {
2775   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2776 
2777   PetscFunctionBegin;
2778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2779   PetscValidType(mat, 1);
2780   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2781   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2782   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2783 
2784   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2785   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2786   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);
2787   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);
2788   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);
2789   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2790   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2791   MatCheckPreallocated(mat, 1);
2792 
2793   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2794   PetscCall(VecLockReadPush(v1));
2795   PetscCall((*op)(mat, v1, v2, v3));
2796   PetscCall(VecLockReadPop(v1));
2797   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2798   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2799   PetscFunctionReturn(PETSC_SUCCESS);
2800 }
2801 
2802 /*@
2803    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2804 
2805    Neighbor-wise Collective
2806 
2807    Input Parameters:
2808 +  mat - the matrix
2809 .  v1 - the vector to be multiplied by the Hermitian transpose
2810 -  v2 - the vector to be added to the result
2811 
2812    Output Parameter:
2813 .  v3 - the result
2814 
2815    Level: beginner
2816 
2817    Note:
2818    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2819    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2820 
2821 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2822 @*/
2823 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2824 {
2825   PetscFunctionBegin;
2826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2827   PetscValidType(mat, 1);
2828   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2829   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2830   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2831 
2832   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2833   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2834   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2835   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);
2836   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);
2837   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);
2838   MatCheckPreallocated(mat, 1);
2839 
2840   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2841   PetscCall(VecLockReadPush(v1));
2842   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2843   else {
2844     Vec w, z;
2845     PetscCall(VecDuplicate(v1, &w));
2846     PetscCall(VecCopy(v1, w));
2847     PetscCall(VecConjugate(w));
2848     PetscCall(VecDuplicate(v3, &z));
2849     PetscCall(MatMultTranspose(mat, w, z));
2850     PetscCall(VecDestroy(&w));
2851     PetscCall(VecConjugate(z));
2852     if (v2 != v3) {
2853       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2854     } else {
2855       PetscCall(VecAXPY(v3, 1.0, z));
2856     }
2857     PetscCall(VecDestroy(&z));
2858   }
2859   PetscCall(VecLockReadPop(v1));
2860   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2861   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2862   PetscFunctionReturn(PETSC_SUCCESS);
2863 }
2864 
2865 /*@C
2866    MatGetFactorType - gets the type of factorization it is
2867 
2868    Not Collective
2869 
2870    Input Parameter:
2871 .  mat - the matrix
2872 
2873    Output Parameter:
2874 .  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`
2875 
2876    Level: intermediate
2877 
2878 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2879           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2880 @*/
2881 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2882 {
2883   PetscFunctionBegin;
2884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2885   PetscValidType(mat, 1);
2886   PetscValidPointer(t, 2);
2887   *t = mat->factortype;
2888   PetscFunctionReturn(PETSC_SUCCESS);
2889 }
2890 
2891 /*@C
2892    MatSetFactorType - sets the type of factorization it is
2893 
2894    Logically Collective
2895 
2896    Input Parameters:
2897 +  mat - the matrix
2898 -  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`
2899 
2900    Level: intermediate
2901 
2902 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2903           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2904 @*/
2905 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2906 {
2907   PetscFunctionBegin;
2908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2909   PetscValidType(mat, 1);
2910   mat->factortype = t;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915    MatGetInfo - Returns information about matrix storage (number of
2916    nonzeros, memory, etc.).
2917 
2918    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2919 
2920    Input Parameters:
2921 +  mat - the matrix
2922 -  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)
2923 
2924    Output Parameter:
2925 .  info - matrix information context
2926 
2927    Notes:
2928    The `MatInfo` context contains a variety of matrix data, including
2929    number of nonzeros allocated and used, number of mallocs during
2930    matrix assembly, etc.  Additional information for factored matrices
2931    is provided (such as the fill ratio, number of mallocs during
2932    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2933    when using the runtime options
2934 $       -info -mat_view ::ascii_info
2935 
2936    Example:
2937    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2938    data within the MatInfo context.  For example,
2939 .vb
2940       MatInfo info;
2941       Mat     A;
2942       double  mal, nz_a, nz_u;
2943 
2944       MatGetInfo(A,MAT_LOCAL,&info);
2945       mal  = info.mallocs;
2946       nz_a = info.nz_allocated;
2947 .ve
2948 
2949    Fortran users should declare info as a double precision
2950    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2951    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2952    a complete list of parameter names.
2953 .vb
2954       double  precision info(MAT_INFO_SIZE)
2955       double  precision mal, nz_a
2956       Mat     A
2957       integer ierr
2958 
2959       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2960       mal = info(MAT_INFO_MALLOCS)
2961       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2962 .ve
2963 
2964     Level: intermediate
2965 
2966     Developer Note:
2967     The Fortran interface is not autogenerated as the
2968     interface definition cannot be generated correctly [due to `MatInfo` argument]
2969 
2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2971 @*/
2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2973 {
2974   PetscFunctionBegin;
2975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2976   PetscValidType(mat, 1);
2977   PetscValidPointer(info, 3);
2978   MatCheckPreallocated(mat, 1);
2979   PetscUseTypeMethod(mat, getinfo, flag, info);
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*
2984    This is used by external packages where it is not easy to get the info from the actual
2985    matrix factorization.
2986 */
2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2988 {
2989   PetscFunctionBegin;
2990   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2991   PetscFunctionReturn(PETSC_SUCCESS);
2992 }
2993 
2994 /*@C
2995    MatLUFactor - Performs in-place LU factorization of matrix.
2996 
2997    Collective
2998 
2999    Input Parameters:
3000 +  mat - the matrix
3001 .  row - row permutation
3002 .  col - column permutation
3003 -  info - options for factorization, includes
3004 .vb
3005           fill - expected fill as ratio of original fill.
3006           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007                    Run with the option -info to determine an optimal value to use
3008 .ve
3009    Level: developer
3010 
3011    Notes:
3012    Most users should employ the `KSP` interface for linear solvers
3013    instead of working directly with matrix algebra routines such as this.
3014    See, e.g., `KSPCreate()`.
3015 
3016    This changes the state of the matrix to a factored matrix; it cannot be used
3017    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3018 
3019    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3020    when not using `KSP`.
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 .vb
3065       levels - number of levels of fill.
3066       expected fill - as ratio of original fill.
3067       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3068                 missing diagonal entries)
3069 .ve
3070 
3071    Level: developer
3072 
3073    Notes:
3074    Most users should employ the `KSP` interface for linear solvers
3075    instead of working directly with matrix algebra routines such as this.
3076    See, e.g., `KSPCreate()`.
3077 
3078    Probably really in-place only when level of fill is zero, otherwise allocates
3079    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3080    when not using `KSP`.
3081 
3082    Developer Note:
3083    The Fortran interface is not autogenerated as the
3084    interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3087 @*/
3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3093   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3094   PetscValidPointer(info, 4);
3095   PetscValidType(mat, 1);
3096   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3099   MatCheckPreallocated(mat, 1);
3100 
3101   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3102   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3103   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3105   PetscFunctionReturn(PETSC_SUCCESS);
3106 }
3107 
3108 /*@C
3109    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3110    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3111 
3112    Collective
3113 
3114    Input Parameters:
3115 +  fact - the factor matrix obtained with `MatGetFactor()`
3116 .  mat - the matrix
3117 .  row - the row permutation
3118 .  col - the column permutation
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
3145   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3147   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3148   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3149   if (info) PetscValidPointer(info, 5);
3150   PetscValidType(fact, 1);
3151   PetscValidType(mat, 2);
3152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3153   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3154   MatCheckPreallocated(mat, 2);
3155   if (!info) {
3156     PetscCall(MatFactorInfoInitialize(&tinfo));
3157     info = &tinfo;
3158   }
3159 
3160   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3161   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3162   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3163   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3164   PetscFunctionReturn(PETSC_SUCCESS);
3165 }
3166 
3167 /*@C
3168    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3169    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3170 
3171    Collective
3172 
3173    Input Parameters:
3174 +  fact - the factor matrix obtained with `MatGetFactor()`
3175 .  mat - the matrix
3176 -  info - options for factorization
3177 
3178    Level: developer
3179 
3180    Notes:
3181    See `MatLUFactor()` for in-place factorization.  See
3182    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3183 
3184    Most users should employ the `KSP` interface for linear solvers
3185    instead of working directly with matrix algebra routines such as this.
3186    See, e.g., `KSPCreate()`.
3187 
3188     Developer Note:
3189     The Fortran interface is not autogenerated as the
3190     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3191 
3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3193 @*/
3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3195 {
3196   MatFactorInfo tinfo;
3197 
3198   PetscFunctionBegin;
3199   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3201   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3202   PetscValidType(fact, 1);
3203   PetscValidType(mat, 2);
3204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3205   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3206              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3207 
3208   MatCheckPreallocated(mat, 2);
3209   if (!info) {
3210     PetscCall(MatFactorInfoInitialize(&tinfo));
3211     info = &tinfo;
3212   }
3213 
3214   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3215   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3216   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3217   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3218   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3219   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3220   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3221   PetscFunctionReturn(PETSC_SUCCESS);
3222 }
3223 
3224 /*@C
3225    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3226    symmetric matrix.
3227 
3228    Collective
3229 
3230    Input Parameters:
3231 +  mat - the matrix
3232 .  perm - row and column permutations
3233 -  f - expected fill as ratio of original fill
3234 
3235    Level: developer
3236 
3237    Notes:
3238    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3239    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3240 
3241    Most users should employ the `KSP` interface for linear solvers
3242    instead of working directly with matrix algebra routines such as this.
3243    See, e.g., `KSPCreate()`.
3244 
3245    Developer Note:
3246    The Fortran interface is not autogenerated as the
3247    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3248 
3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3250           `MatGetOrdering()`
3251 @*/
3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3253 {
3254   MatFactorInfo tinfo;
3255 
3256   PetscFunctionBegin;
3257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3258   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3259   if (info) PetscValidPointer(info, 3);
3260   PetscValidType(mat, 1);
3261   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3262   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3263   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3264   MatCheckPreallocated(mat, 1);
3265   if (!info) {
3266     PetscCall(MatFactorInfoInitialize(&tinfo));
3267     info = &tinfo;
3268   }
3269 
3270   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3271   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3272   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3273   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3274   PetscFunctionReturn(PETSC_SUCCESS);
3275 }
3276 
3277 /*@C
3278    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3279    of a symmetric matrix.
3280 
3281    Collective
3282 
3283    Input Parameters:
3284 +  fact - the factor matrix obtained with `MatGetFactor()`
3285 .  mat - the matrix
3286 .  perm - row and column permutations
3287 -  info - options for factorization, includes
3288 .vb
3289           fill - expected fill as ratio of original fill.
3290           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3291                    Run with the option -info to determine an optimal value to use
3292 .ve
3293 
3294    Level: developer
3295 
3296    Notes:
3297    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3298    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3299 
3300    Most users should employ the `KSP` interface for linear solvers
3301    instead of working directly with matrix algebra routines such as this.
3302    See, e.g., `KSPCreate()`.
3303 
3304    Developer Note:
3305    The Fortran interface is not autogenerated as the
3306    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3307 
3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3309           `MatGetOrdering()`
3310 @*/
3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3312 {
3313   MatFactorInfo tinfo;
3314 
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3319   if (info) PetscValidPointer(info, 4);
3320   PetscValidType(fact, 1);
3321   PetscValidType(mat, 2);
3322   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3325   MatCheckPreallocated(mat, 2);
3326   if (!info) {
3327     PetscCall(MatFactorInfoInitialize(&tinfo));
3328     info = &tinfo;
3329   }
3330 
3331   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3332   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3333   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3334   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3335   PetscFunctionReturn(PETSC_SUCCESS);
3336 }
3337 
3338 /*@C
3339    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3340    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3341    `MatCholeskyFactorSymbolic()`.
3342 
3343    Collective
3344 
3345    Input Parameters:
3346 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3347 .  mat - the initial matrix that is to be factored
3348 -  info - options for factorization
3349 
3350    Level: developer
3351 
3352    Note:
3353    Most users should employ the `KSP` interface for linear solvers
3354    instead of working directly with matrix algebra routines such as this.
3355    See, e.g., `KSPCreate()`.
3356 
3357    Developer Note:
3358    The Fortran interface is not autogenerated as the
3359    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3360 
3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3362 @*/
3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3364 {
3365   MatFactorInfo tinfo;
3366 
3367   PetscFunctionBegin;
3368   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3370   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3371   PetscValidType(fact, 1);
3372   PetscValidType(mat, 2);
3373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3374   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,
3375              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3376   MatCheckPreallocated(mat, 2);
3377   if (!info) {
3378     PetscCall(MatFactorInfoInitialize(&tinfo));
3379     info = &tinfo;
3380   }
3381 
3382   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3383   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3384   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3385   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3386   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3387   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3388   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3389   PetscFunctionReturn(PETSC_SUCCESS);
3390 }
3391 
3392 /*@
3393    MatQRFactor - Performs in-place QR factorization of matrix.
3394 
3395    Collective
3396 
3397    Input Parameters:
3398 +  mat - the matrix
3399 .  col - column permutation
3400 -  info - options for factorization, includes
3401 .vb
3402           fill - expected fill as ratio of original fill.
3403           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3404                    Run with the option -info to determine an optimal value to use
3405 .ve
3406 
3407    Level: developer
3408 
3409    Notes:
3410    Most users should employ the `KSP` interface for linear solvers
3411    instead of working directly with matrix algebra routines such as this.
3412    See, e.g., `KSPCreate()`.
3413 
3414    This changes the state of the matrix to a factored matrix; it cannot be used
3415    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3416 
3417    Developer Note:
3418    The Fortran interface is not autogenerated as the
3419    interface definition cannot be generated correctly [due to MatFactorInfo]
3420 
3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3422           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3423 @*/
3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3425 {
3426   PetscFunctionBegin;
3427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3428   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3429   if (info) PetscValidPointer(info, 3);
3430   PetscValidType(mat, 1);
3431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3433   MatCheckPreallocated(mat, 1);
3434   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3435   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3436   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3437   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3438   PetscFunctionReturn(PETSC_SUCCESS);
3439 }
3440 
3441 /*@
3442    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3443    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3444 
3445    Collective
3446 
3447    Input Parameters:
3448 +  fact - the factor matrix obtained with `MatGetFactor()`
3449 .  mat - the matrix
3450 .  col - column permutation
3451 -  info - options for factorization, includes
3452 .vb
3453           fill - expected fill as ratio of original fill.
3454           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3455                    Run with the option -info to determine an optimal value to use
3456 .ve
3457 
3458    Level: developer
3459 
3460    Note:
3461    Most users should employ the `KSP` interface for linear solvers
3462    instead of working directly with matrix algebra routines such as this.
3463    See, e.g., `KSPCreate()`.
3464 
3465    Developer Note:
3466    The Fortran interface is not autogenerated as the
3467    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3468 
3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3470 @*/
3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3472 {
3473   MatFactorInfo tinfo;
3474 
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3478   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3479   if (info) PetscValidPointer(info, 4);
3480   PetscValidType(fact, 1);
3481   PetscValidType(mat, 2);
3482   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3483   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3484   MatCheckPreallocated(mat, 2);
3485   if (!info) {
3486     PetscCall(MatFactorInfoInitialize(&tinfo));
3487     info = &tinfo;
3488   }
3489 
3490   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3491   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3492   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3493   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3494   PetscFunctionReturn(PETSC_SUCCESS);
3495 }
3496 
3497 /*@
3498    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3499    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3500 
3501    Collective
3502 
3503    Input Parameters:
3504 +  fact - the factor matrix obtained with `MatGetFactor()`
3505 .  mat - the matrix
3506 -  info - options for factorization
3507 
3508    Level: developer
3509 
3510    Notes:
3511    See `MatQRFactor()` for in-place factorization.
3512 
3513    Most users should employ the `KSP` interface for linear solvers
3514    instead of working directly with matrix algebra routines such as this.
3515    See, e.g., `KSPCreate()`.
3516 
3517    Developer Note:
3518    The Fortran interface is not autogenerated as the
3519    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3520 
3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3522 @*/
3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3524 {
3525   MatFactorInfo tinfo;
3526 
3527   PetscFunctionBegin;
3528   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3530   PetscValidType(fact, 1);
3531   PetscValidType(mat, 2);
3532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3533   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,
3534              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3535 
3536   MatCheckPreallocated(mat, 2);
3537   if (!info) {
3538     PetscCall(MatFactorInfoInitialize(&tinfo));
3539     info = &tinfo;
3540   }
3541 
3542   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3543   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3544   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3548   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3549   PetscFunctionReturn(PETSC_SUCCESS);
3550 }
3551 
3552 /*@
3553    MatSolve - Solves A x = b, given a factored matrix.
3554 
3555    Neighbor-wise Collective
3556 
3557    Input Parameters:
3558 +  mat - the factored matrix
3559 -  b - the right-hand-side vector
3560 
3561    Output Parameter:
3562 .  x - the result vector
3563 
3564    Level: developer
3565 
3566    Notes:
3567    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3568    call `MatSolve`(A,x,x).
3569 
3570    Most users should employ the `KSP` interface for linear solvers
3571    instead of working directly with matrix algebra routines such as this.
3572    See, e.g., `KSPCreate()`.
3573 
3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3575 @*/
3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3577 {
3578   PetscFunctionBegin;
3579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3580   PetscValidType(mat, 1);
3581   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3582   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3583   PetscCheckSameComm(mat, 1, b, 2);
3584   PetscCheckSameComm(mat, 1, x, 3);
3585   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3586   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);
3587   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);
3588   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);
3589   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3590   MatCheckPreallocated(mat, 1);
3591 
3592   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3593   if (mat->factorerrortype) {
3594     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3595     PetscCall(VecSetInf(x));
3596   } else PetscUseTypeMethod(mat, solve, b, x);
3597   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3598   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3599   PetscFunctionReturn(PETSC_SUCCESS);
3600 }
3601 
3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3603 {
3604   Vec      b, x;
3605   PetscInt N, i;
3606   PetscErrorCode (*f)(Mat, Vec, Vec);
3607   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3608 
3609   PetscFunctionBegin;
3610   if (A->factorerrortype) {
3611     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3612     PetscCall(MatSetInf(X));
3613     PetscFunctionReturn(PETSC_SUCCESS);
3614   }
3615   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3616   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3617   PetscCall(MatBoundToCPU(A, &Abound));
3618   if (!Abound) {
3619     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3620     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3621   }
3622 #if defined(PETSC_HAVE_CUDA)
3623   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3624   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3625 #elif (PETSC_HAVE_HIP)
3626   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3627   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3628 #endif
3629   PetscCall(MatGetSize(B, NULL, &N));
3630   for (i = 0; i < N; i++) {
3631     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3632     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3633     PetscCall((*f)(A, b, x));
3634     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3635     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3636   }
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3639   PetscFunctionReturn(PETSC_SUCCESS);
3640 }
3641 
3642 /*@
3643    MatMatSolve - Solves A X = B, given a factored matrix.
3644 
3645    Neighbor-wise Collective
3646 
3647    Input Parameters:
3648 +  A - the factored matrix
3649 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3650 
3651    Output Parameter:
3652 .  X - the result matrix (dense matrix)
3653 
3654    Level: developer
3655 
3656    Note:
3657    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3658    otherwise, `B` and `X` cannot be the same.
3659 
3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3661 @*/
3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3663 {
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3666   PetscValidType(A, 1);
3667   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3668   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3669   PetscCheckSameComm(A, 1, B, 2);
3670   PetscCheckSameComm(A, 1, X, 3);
3671   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);
3672   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);
3673   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");
3674   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3675   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3676   MatCheckPreallocated(A, 1);
3677 
3678   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3679   if (!A->ops->matsolve) {
3680     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3681     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3682   } else PetscUseTypeMethod(A, matsolve, B, X);
3683   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3684   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3685   PetscFunctionReturn(PETSC_SUCCESS);
3686 }
3687 
3688 /*@
3689    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3690 
3691    Neighbor-wise Collective
3692 
3693    Input Parameters:
3694 +  A - the factored matrix
3695 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3696 
3697    Output Parameter:
3698 .  X - the result matrix (dense matrix)
3699 
3700    Level: developer
3701 
3702    Note:
3703    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3704    call `MatMatSolveTranspose`(A,X,X).
3705 
3706 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3707 @*/
3708 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3709 {
3710   PetscFunctionBegin;
3711   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3712   PetscValidType(A, 1);
3713   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3714   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3715   PetscCheckSameComm(A, 1, B, 2);
3716   PetscCheckSameComm(A, 1, X, 3);
3717   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3718   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);
3719   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);
3720   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);
3721   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");
3722   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3723   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3724   MatCheckPreallocated(A, 1);
3725 
3726   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3727   if (!A->ops->matsolvetranspose) {
3728     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3729     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3730   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3731   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3732   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3733   PetscFunctionReturn(PETSC_SUCCESS);
3734 }
3735 
3736 /*@
3737    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3738 
3739    Neighbor-wise Collective
3740 
3741    Input Parameters:
3742 +  A - the factored matrix
3743 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3744 
3745    Output Parameter:
3746 .  X - the result matrix (dense matrix)
3747 
3748    Level: developer
3749 
3750    Note:
3751    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
3752    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3753 
3754 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3755 @*/
3756 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3757 {
3758   PetscFunctionBegin;
3759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3760   PetscValidType(A, 1);
3761   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3762   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3763   PetscCheckSameComm(A, 1, Bt, 2);
3764   PetscCheckSameComm(A, 1, X, 3);
3765 
3766   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3767   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);
3768   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);
3769   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");
3770   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3771   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3772   MatCheckPreallocated(A, 1);
3773 
3774   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3775   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3776   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3777   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3778   PetscFunctionReturn(PETSC_SUCCESS);
3779 }
3780 
3781 /*@
3782    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3783                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3784 
3785    Neighbor-wise Collective
3786 
3787    Input Parameters:
3788 +  mat - the factored matrix
3789 -  b - the right-hand-side vector
3790 
3791    Output Parameter:
3792 .  x - the result vector
3793 
3794    Level: developer
3795 
3796    Notes:
3797    `MatSolve()` should be used for most applications, as it performs
3798    a forward solve followed by a backward solve.
3799 
3800    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3801    call `MatForwardSolve`(A,x,x).
3802 
3803    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3804    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3805    `MatForwardSolve()` solves U^T*D y = b, and
3806    `MatBackwardSolve()` solves U x = y.
3807    Thus they do not provide a symmetric preconditioner.
3808 
3809 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3810 @*/
3811 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3812 {
3813   PetscFunctionBegin;
3814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3815   PetscValidType(mat, 1);
3816   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3817   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3818   PetscCheckSameComm(mat, 1, b, 2);
3819   PetscCheckSameComm(mat, 1, x, 3);
3820   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3821   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);
3822   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);
3823   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);
3824   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3825   MatCheckPreallocated(mat, 1);
3826 
3827   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3828   PetscUseTypeMethod(mat, forwardsolve, b, x);
3829   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3830   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3831   PetscFunctionReturn(PETSC_SUCCESS);
3832 }
3833 
3834 /*@
3835    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3836                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3837 
3838    Neighbor-wise Collective
3839 
3840    Input Parameters:
3841 +  mat - the factored matrix
3842 -  b - the right-hand-side vector
3843 
3844    Output Parameter:
3845 .  x - the result vector
3846 
3847    Level: developer
3848 
3849    Notes:
3850    `MatSolve()` should be used for most applications, as it performs
3851    a forward solve followed by a backward solve.
3852 
3853    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3854    call `MatBackwardSolve`(A,x,x).
3855 
3856    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3857    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3858    `MatForwardSolve()` solves U^T*D y = b, and
3859    `MatBackwardSolve()` solves U x = y.
3860    Thus they do not provide a symmetric preconditioner.
3861 
3862 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3863 @*/
3864 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3865 {
3866   PetscFunctionBegin;
3867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3868   PetscValidType(mat, 1);
3869   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3870   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3871   PetscCheckSameComm(mat, 1, b, 2);
3872   PetscCheckSameComm(mat, 1, x, 3);
3873   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3874   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);
3875   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);
3876   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);
3877   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3878   MatCheckPreallocated(mat, 1);
3879 
3880   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3881   PetscUseTypeMethod(mat, backwardsolve, b, x);
3882   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3883   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3884   PetscFunctionReturn(PETSC_SUCCESS);
3885 }
3886 
3887 /*@
3888    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3889 
3890    Neighbor-wise Collective
3891 
3892    Input Parameters:
3893 +  mat - the factored matrix
3894 .  b - the right-hand-side vector
3895 -  y - the vector to be added to
3896 
3897    Output Parameter:
3898 .  x - the result vector
3899 
3900    Level: developer
3901 
3902    Note:
3903    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3904    call `MatSolveAdd`(A,x,y,x).
3905 
3906 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3907 @*/
3908 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3909 {
3910   PetscScalar one = 1.0;
3911   Vec         tmp;
3912 
3913   PetscFunctionBegin;
3914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3915   PetscValidType(mat, 1);
3916   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3917   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3918   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3919   PetscCheckSameComm(mat, 1, b, 2);
3920   PetscCheckSameComm(mat, 1, y, 3);
3921   PetscCheckSameComm(mat, 1, x, 4);
3922   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3923   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);
3924   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);
3925   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);
3926   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);
3927   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);
3928   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3929   MatCheckPreallocated(mat, 1);
3930 
3931   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3932   if (mat->factorerrortype) {
3933     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3934     PetscCall(VecSetInf(x));
3935   } else if (mat->ops->solveadd) {
3936     PetscUseTypeMethod(mat, solveadd, b, y, x);
3937   } else {
3938     /* do the solve then the add manually */
3939     if (x != y) {
3940       PetscCall(MatSolve(mat, b, x));
3941       PetscCall(VecAXPY(x, one, y));
3942     } else {
3943       PetscCall(VecDuplicate(x, &tmp));
3944       PetscCall(VecCopy(x, tmp));
3945       PetscCall(MatSolve(mat, b, x));
3946       PetscCall(VecAXPY(x, one, tmp));
3947       PetscCall(VecDestroy(&tmp));
3948     }
3949   }
3950   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3951   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3952   PetscFunctionReturn(PETSC_SUCCESS);
3953 }
3954 
3955 /*@
3956    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3957 
3958    Neighbor-wise Collective
3959 
3960    Input Parameters:
3961 +  mat - the factored matrix
3962 -  b - the right-hand-side vector
3963 
3964    Output Parameter:
3965 .  x - the result vector
3966 
3967    Level: developer
3968 
3969    Notes:
3970    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3971    call `MatSolveTranspose`(A,x,x).
3972 
3973    Most users should employ the `KSP` interface for linear solvers
3974    instead of working directly with matrix algebra routines such as this.
3975    See, e.g., `KSPCreate()`.
3976 
3977 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3978 @*/
3979 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3980 {
3981   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3982 
3983   PetscFunctionBegin;
3984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3985   PetscValidType(mat, 1);
3986   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3987   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3988   PetscCheckSameComm(mat, 1, b, 2);
3989   PetscCheckSameComm(mat, 1, x, 3);
3990   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3991   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);
3992   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);
3993   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3994   MatCheckPreallocated(mat, 1);
3995   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3996   if (mat->factorerrortype) {
3997     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3998     PetscCall(VecSetInf(x));
3999   } else {
4000     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4001     PetscCall((*f)(mat, b, x));
4002   }
4003   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4004   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4005   PetscFunctionReturn(PETSC_SUCCESS);
4006 }
4007 
4008 /*@
4009    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4010                       factored matrix.
4011 
4012    Neighbor-wise Collective
4013 
4014    Input Parameters:
4015 +  mat - the factored matrix
4016 .  b - the right-hand-side vector
4017 -  y - the vector to be added to
4018 
4019    Output Parameter:
4020 .  x - the result vector
4021 
4022    Level: developer
4023 
4024    Note:
4025    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4026    call `MatSolveTransposeAdd`(A,x,y,x).
4027 
4028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4029 @*/
4030 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4031 {
4032   PetscScalar one = 1.0;
4033   Vec         tmp;
4034   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4035 
4036   PetscFunctionBegin;
4037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4038   PetscValidType(mat, 1);
4039   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4040   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4041   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4042   PetscCheckSameComm(mat, 1, b, 2);
4043   PetscCheckSameComm(mat, 1, y, 3);
4044   PetscCheckSameComm(mat, 1, x, 4);
4045   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4046   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);
4047   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);
4048   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);
4049   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);
4050   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4051   MatCheckPreallocated(mat, 1);
4052 
4053   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4054   if (mat->factorerrortype) {
4055     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4056     PetscCall(VecSetInf(x));
4057   } else if (f) {
4058     PetscCall((*f)(mat, b, y, x));
4059   } else {
4060     /* do the solve then the add manually */
4061     if (x != y) {
4062       PetscCall(MatSolveTranspose(mat, b, x));
4063       PetscCall(VecAXPY(x, one, y));
4064     } else {
4065       PetscCall(VecDuplicate(x, &tmp));
4066       PetscCall(VecCopy(x, tmp));
4067       PetscCall(MatSolveTranspose(mat, b, x));
4068       PetscCall(VecAXPY(x, one, tmp));
4069       PetscCall(VecDestroy(&tmp));
4070     }
4071   }
4072   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4073   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4074   PetscFunctionReturn(PETSC_SUCCESS);
4075 }
4076 
4077 /*@
4078    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4079 
4080    Neighbor-wise Collective
4081 
4082    Input Parameters:
4083 +  mat - the matrix
4084 .  b - the right hand side
4085 .  omega - the relaxation factor
4086 .  flag - flag indicating the type of SOR (see below)
4087 .  shift -  diagonal shift
4088 .  its - the number of iterations
4089 -  lits - the number of local iterations
4090 
4091    Output Parameter:
4092 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4093 
4094    SOR Flags:
4095 +     `SOR_FORWARD_SWEEP` - forward SOR
4096 .     `SOR_BACKWARD_SWEEP` - backward SOR
4097 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4098 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4099 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4100 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4101 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4102 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4103          upper/lower triangular part of matrix to
4104          vector (with omega)
4105 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4106 
4107    Level: developer
4108 
4109    Notes:
4110    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4111    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4112    on each processor.
4113 
4114    Application programmers will not generally use `MatSOR()` directly,
4115    but instead will employ the `KSP`/`PC` interface.
4116 
4117    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4118 
4119    Most users should employ the `KSP` interface for linear solvers
4120    instead of working directly with matrix algebra routines such as this.
4121    See, e.g., `KSPCreate()`.
4122 
4123    Vectors `x` and `b` CANNOT be the same
4124 
4125    The flags are implemented as bitwise inclusive or operations.
4126    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4127    to specify a zero initial guess for SSOR.
4128 
4129    Developer Note:
4130    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4131 
4132 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4133 @*/
4134 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4135 {
4136   PetscFunctionBegin;
4137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4138   PetscValidType(mat, 1);
4139   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4140   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4141   PetscCheckSameComm(mat, 1, b, 2);
4142   PetscCheckSameComm(mat, 1, x, 8);
4143   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4144   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4145   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);
4146   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);
4147   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);
4148   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4149   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4150   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4151 
4152   MatCheckPreallocated(mat, 1);
4153   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4154   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4155   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4156   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4157   PetscFunctionReturn(PETSC_SUCCESS);
4158 }
4159 
4160 /*
4161       Default matrix copy routine.
4162 */
4163 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4164 {
4165   PetscInt           i, rstart = 0, rend = 0, nz;
4166   const PetscInt    *cwork;
4167   const PetscScalar *vwork;
4168 
4169   PetscFunctionBegin;
4170   if (B->assembled) PetscCall(MatZeroEntries(B));
4171   if (str == SAME_NONZERO_PATTERN) {
4172     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4173     for (i = rstart; i < rend; i++) {
4174       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4175       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4176       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4177     }
4178   } else {
4179     PetscCall(MatAYPX(B, 0.0, A, str));
4180   }
4181   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4182   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4183   PetscFunctionReturn(PETSC_SUCCESS);
4184 }
4185 
4186 /*@
4187    MatCopy - Copies a matrix to another matrix.
4188 
4189    Collective
4190 
4191    Input Parameters:
4192 +  A - the matrix
4193 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4194 
4195    Output Parameter:
4196 .  B - where the copy is put
4197 
4198    Level: intermediate
4199 
4200    Notes:
4201    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4202 
4203    `MatCopy()` copies the matrix entries of a matrix to another existing
4204    matrix (after first zeroing the second matrix).  A related routine is
4205    `MatConvert()`, which first creates a new matrix and then copies the data.
4206 
4207 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4208 @*/
4209 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4210 {
4211   PetscInt i;
4212 
4213   PetscFunctionBegin;
4214   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4215   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4216   PetscValidType(A, 1);
4217   PetscValidType(B, 2);
4218   PetscCheckSameComm(A, 1, B, 2);
4219   MatCheckPreallocated(B, 2);
4220   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4221   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4222   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,
4223              A->cmap->N, B->cmap->N);
4224   MatCheckPreallocated(A, 1);
4225   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4226 
4227   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4228   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4229   else PetscCall(MatCopy_Basic(A, B, str));
4230 
4231   B->stencil.dim = A->stencil.dim;
4232   B->stencil.noc = A->stencil.noc;
4233   for (i = 0; i <= A->stencil.dim; i++) {
4234     B->stencil.dims[i]   = A->stencil.dims[i];
4235     B->stencil.starts[i] = A->stencil.starts[i];
4236   }
4237 
4238   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4239   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4240   PetscFunctionReturn(PETSC_SUCCESS);
4241 }
4242 
4243 /*@C
4244    MatConvert - Converts a matrix to another matrix, either of the same
4245    or different type.
4246 
4247    Collective
4248 
4249    Input Parameters:
4250 +  mat - the matrix
4251 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4252    same type as the original matrix.
4253 -  reuse - denotes if the destination matrix is to be created or reused.
4254    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
4255    `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).
4256 
4257    Output Parameter:
4258 .  M - pointer to place new matrix
4259 
4260    Level: intermediate
4261 
4262    Notes:
4263    `MatConvert()` first creates a new matrix and then copies the data from
4264    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4265    entries of one matrix to another already existing matrix context.
4266 
4267    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4268    the MPI communicator of the generated matrix is always the same as the communicator
4269    of the input matrix.
4270 
4271 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4272 @*/
4273 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4274 {
4275   PetscBool  sametype, issame, flg;
4276   PetscBool3 issymmetric, ishermitian;
4277   char       convname[256], mtype[256];
4278   Mat        B;
4279 
4280   PetscFunctionBegin;
4281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4282   PetscValidType(mat, 1);
4283   PetscValidPointer(M, 4);
4284   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4285   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4286   MatCheckPreallocated(mat, 1);
4287 
4288   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4289   if (flg) newtype = mtype;
4290 
4291   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4292   PetscCall(PetscStrcmp(newtype, "same", &issame));
4293   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4294   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");
4295 
4296   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4297     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4298     PetscFunctionReturn(PETSC_SUCCESS);
4299   }
4300 
4301   /* Cache Mat options because some converters use MatHeaderReplace  */
4302   issymmetric = mat->symmetric;
4303   ishermitian = mat->hermitian;
4304 
4305   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4306     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4307     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4308   } else {
4309     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4310     const char *prefix[3]                                 = {"seq", "mpi", ""};
4311     PetscInt    i;
4312     /*
4313        Order of precedence:
4314        0) See if newtype is a superclass of the current matrix.
4315        1) See if a specialized converter is known to the current matrix.
4316        2) See if a specialized converter is known to the desired matrix class.
4317        3) See if a good general converter is registered for the desired class
4318           (as of 6/27/03 only MATMPIADJ falls into this category).
4319        4) See if a good general converter is known for the current matrix.
4320        5) Use a really basic converter.
4321     */
4322 
4323     /* 0) See if newtype is a superclass of the current matrix.
4324           i.e mat is mpiaij and newtype is aij */
4325     for (i = 0; i < 2; i++) {
4326       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4327       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4328       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4329       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4330       if (flg) {
4331         if (reuse == MAT_INPLACE_MATRIX) {
4332           PetscCall(PetscInfo(mat, "Early return\n"));
4333           PetscFunctionReturn(PETSC_SUCCESS);
4334         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4335           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4336           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4337           PetscFunctionReturn(PETSC_SUCCESS);
4338         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4339           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4340           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4341           PetscFunctionReturn(PETSC_SUCCESS);
4342         }
4343       }
4344     }
4345     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4346     for (i = 0; i < 3; i++) {
4347       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4353       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4354       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4355       if (conv) goto foundconv;
4356     }
4357 
4358     /* 2)  See if a specialized converter is known to the desired matrix class. */
4359     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4360     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4361     PetscCall(MatSetType(B, newtype));
4362     for (i = 0; i < 3; i++) {
4363       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4368       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4369       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4370       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4371       if (conv) {
4372         PetscCall(MatDestroy(&B));
4373         goto foundconv;
4374       }
4375     }
4376 
4377     /* 3) See if a good general converter is registered for the desired class */
4378     conv = B->ops->convertfrom;
4379     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4380     PetscCall(MatDestroy(&B));
4381     if (conv) goto foundconv;
4382 
4383     /* 4) See if a good general converter is known for the current matrix */
4384     if (mat->ops->convert) conv = mat->ops->convert;
4385     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4386     if (conv) goto foundconv;
4387 
4388     /* 5) Use a really basic converter. */
4389     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4390     conv = MatConvert_Basic;
4391 
4392   foundconv:
4393     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4394     PetscCall((*conv)(mat, newtype, reuse, M));
4395     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4396       /* the block sizes must be same if the mappings are copied over */
4397       (*M)->rmap->bs = mat->rmap->bs;
4398       (*M)->cmap->bs = mat->cmap->bs;
4399       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4400       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4401       (*M)->rmap->mapping = mat->rmap->mapping;
4402       (*M)->cmap->mapping = mat->cmap->mapping;
4403     }
4404     (*M)->stencil.dim = mat->stencil.dim;
4405     (*M)->stencil.noc = mat->stencil.noc;
4406     for (i = 0; i <= mat->stencil.dim; i++) {
4407       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4408       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4409     }
4410     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4411   }
4412   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4413 
4414   /* Copy Mat options */
4415   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4416   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4417   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4418   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4419   PetscFunctionReturn(PETSC_SUCCESS);
4420 }
4421 
4422 /*@C
4423    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4424 
4425    Not Collective
4426 
4427    Input Parameter:
4428 .  mat - the matrix, must be a factored matrix
4429 
4430    Output Parameter:
4431 .   type - the string name of the package (do not free this string)
4432 
4433    Level: intermediate
4434 
4435    Fortran Note:
4436    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4437 
4438 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4439 @*/
4440 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4441 {
4442   PetscErrorCode (*conv)(Mat, MatSolverType *);
4443 
4444   PetscFunctionBegin;
4445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4446   PetscValidType(mat, 1);
4447   PetscValidPointer(type, 2);
4448   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4449   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4450   if (conv) PetscCall((*conv)(mat, type));
4451   else *type = MATSOLVERPETSC;
4452   PetscFunctionReturn(PETSC_SUCCESS);
4453 }
4454 
4455 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4456 struct _MatSolverTypeForSpecifcType {
4457   MatType mtype;
4458   /* no entry for MAT_FACTOR_NONE */
4459   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4460   MatSolverTypeForSpecifcType next;
4461 };
4462 
4463 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4464 struct _MatSolverTypeHolder {
4465   char                       *name;
4466   MatSolverTypeForSpecifcType handlers;
4467   MatSolverTypeHolder         next;
4468 };
4469 
4470 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4471 
4472 /*@C
4473    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4474 
4475    Input Parameters:
4476 +    package - name of the package, for example petsc or superlu
4477 .    mtype - the matrix type that works with this package
4478 .    ftype - the type of factorization supported by the package
4479 -    createfactor - routine that will create the factored matrix ready to be used
4480 
4481     Level: developer
4482 
4483 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4484 @*/
4485 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4486 {
4487   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4488   PetscBool                   flg;
4489   MatSolverTypeForSpecifcType inext, iprev = NULL;
4490 
4491   PetscFunctionBegin;
4492   PetscCall(MatInitializePackage());
4493   if (!next) {
4494     PetscCall(PetscNew(&MatSolverTypeHolders));
4495     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4496     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4497     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4498     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4499     PetscFunctionReturn(PETSC_SUCCESS);
4500   }
4501   while (next) {
4502     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4503     if (flg) {
4504       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4505       inext = next->handlers;
4506       while (inext) {
4507         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4508         if (flg) {
4509           inext->createfactor[(int)ftype - 1] = createfactor;
4510           PetscFunctionReturn(PETSC_SUCCESS);
4511         }
4512         iprev = inext;
4513         inext = inext->next;
4514       }
4515       PetscCall(PetscNew(&iprev->next));
4516       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4517       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4518       PetscFunctionReturn(PETSC_SUCCESS);
4519     }
4520     prev = next;
4521     next = next->next;
4522   }
4523   PetscCall(PetscNew(&prev->next));
4524   PetscCall(PetscStrallocpy(package, &prev->next->name));
4525   PetscCall(PetscNew(&prev->next->handlers));
4526   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4527   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4528   PetscFunctionReturn(PETSC_SUCCESS);
4529 }
4530 
4531 /*@C
4532    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4533 
4534    Input Parameters:
4535 +    type - name of the package, for example petsc or superlu
4536 .    ftype - the type of factorization supported by the type
4537 -    mtype - the matrix type that works with this type
4538 
4539    Output Parameters:
4540 +   foundtype - `PETSC_TRUE` if the type was registered
4541 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4542 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4543 
4544     Level: developer
4545 
4546 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4547 @*/
4548 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4549 {
4550   MatSolverTypeHolder         next = MatSolverTypeHolders;
4551   PetscBool                   flg;
4552   MatSolverTypeForSpecifcType inext;
4553 
4554   PetscFunctionBegin;
4555   if (foundtype) *foundtype = PETSC_FALSE;
4556   if (foundmtype) *foundmtype = PETSC_FALSE;
4557   if (createfactor) *createfactor = NULL;
4558 
4559   if (type) {
4560     while (next) {
4561       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4562       if (flg) {
4563         if (foundtype) *foundtype = PETSC_TRUE;
4564         inext = next->handlers;
4565         while (inext) {
4566           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4567           if (flg) {
4568             if (foundmtype) *foundmtype = PETSC_TRUE;
4569             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4570             PetscFunctionReturn(PETSC_SUCCESS);
4571           }
4572           inext = inext->next;
4573         }
4574       }
4575       next = next->next;
4576     }
4577   } else {
4578     while (next) {
4579       inext = next->handlers;
4580       while (inext) {
4581         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4582         if (flg && inext->createfactor[(int)ftype - 1]) {
4583           if (foundtype) *foundtype = PETSC_TRUE;
4584           if (foundmtype) *foundmtype = PETSC_TRUE;
4585           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4586           PetscFunctionReturn(PETSC_SUCCESS);
4587         }
4588         inext = inext->next;
4589       }
4590       next = next->next;
4591     }
4592     /* try with base classes inext->mtype */
4593     next = MatSolverTypeHolders;
4594     while (next) {
4595       inext = next->handlers;
4596       while (inext) {
4597         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4598         if (flg && inext->createfactor[(int)ftype - 1]) {
4599           if (foundtype) *foundtype = PETSC_TRUE;
4600           if (foundmtype) *foundmtype = PETSC_TRUE;
4601           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4602           PetscFunctionReturn(PETSC_SUCCESS);
4603         }
4604         inext = inext->next;
4605       }
4606       next = next->next;
4607     }
4608   }
4609   PetscFunctionReturn(PETSC_SUCCESS);
4610 }
4611 
4612 PetscErrorCode MatSolverTypeDestroy(void)
4613 {
4614   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4615   MatSolverTypeForSpecifcType inext, iprev;
4616 
4617   PetscFunctionBegin;
4618   while (next) {
4619     PetscCall(PetscFree(next->name));
4620     inext = next->handlers;
4621     while (inext) {
4622       PetscCall(PetscFree(inext->mtype));
4623       iprev = inext;
4624       inext = inext->next;
4625       PetscCall(PetscFree(iprev));
4626     }
4627     prev = next;
4628     next = next->next;
4629     PetscCall(PetscFree(prev));
4630   }
4631   MatSolverTypeHolders = NULL;
4632   PetscFunctionReturn(PETSC_SUCCESS);
4633 }
4634 
4635 /*@C
4636    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4637 
4638    Logically Collective
4639 
4640    Input Parameter:
4641 .  mat - the matrix
4642 
4643    Output Parameter:
4644 .  flg - `PETSC_TRUE` if uses the ordering
4645 
4646    Level: developer
4647 
4648    Note:
4649    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4650    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4651 
4652 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4653 @*/
4654 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4655 {
4656   PetscFunctionBegin;
4657   *flg = mat->canuseordering;
4658   PetscFunctionReturn(PETSC_SUCCESS);
4659 }
4660 
4661 /*@C
4662    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4663 
4664    Logically Collective
4665 
4666    Input Parameters:
4667 +  mat - the matrix obtained with `MatGetFactor()`
4668 -  ftype - the factorization type to be used
4669 
4670    Output Parameter:
4671 .  otype - the preferred ordering type
4672 
4673    Level: developer
4674 
4675 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4676 @*/
4677 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4678 {
4679   PetscFunctionBegin;
4680   *otype = mat->preferredordering[ftype];
4681   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4682   PetscFunctionReturn(PETSC_SUCCESS);
4683 }
4684 
4685 /*@C
4686    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4687 
4688    Collective
4689 
4690    Input Parameters:
4691 +  mat - the matrix
4692 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4693 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4694 
4695    Output Parameter:
4696 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4697 
4698    Options Database Key:
4699 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4700                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4701 
4702    Level: intermediate
4703 
4704    Notes:
4705      Users usually access the factorization solvers via `KSP`
4706 
4707       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4708      such as pastix, superlu, mumps etc.
4709 
4710       PETSc must have been ./configure to use the external solver, using the option --download-package
4711 
4712       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4713       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4714       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4715 
4716    Developer Note:
4717       This should actually be called `MatCreateFactor()` since it creates a new factor object
4718 
4719 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4720           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4721 @*/
4722 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4723 {
4724   PetscBool foundtype, foundmtype;
4725   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4726 
4727   PetscFunctionBegin;
4728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4729   PetscValidType(mat, 1);
4730 
4731   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4732   MatCheckPreallocated(mat, 1);
4733 
4734   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4735   if (!foundtype) {
4736     if (type) {
4737       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],
4738               ((PetscObject)mat)->type_name, type);
4739     } else {
4740       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);
4741     }
4742   }
4743   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4744   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);
4745 
4746   PetscCall((*conv)(mat, ftype, f));
4747   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4748   PetscFunctionReturn(PETSC_SUCCESS);
4749 }
4750 
4751 /*@C
4752    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4753 
4754    Not Collective
4755 
4756    Input Parameters:
4757 +  mat - the matrix
4758 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4759 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4760 
4761    Output Parameter:
4762 .    flg - PETSC_TRUE if the factorization is available
4763 
4764    Level: intermediate
4765 
4766    Notes:
4767       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4768      such as pastix, superlu, mumps etc.
4769 
4770       PETSc must have been ./configure to use the external solver, using the option --download-package
4771 
4772    Developer Note:
4773       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4774 
4775 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4776           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4777 @*/
4778 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4779 {
4780   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4781 
4782   PetscFunctionBegin;
4783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4784   PetscValidType(mat, 1);
4785   PetscValidBoolPointer(flg, 4);
4786 
4787   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4788   MatCheckPreallocated(mat, 1);
4789 
4790   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4791   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4792   PetscFunctionReturn(PETSC_SUCCESS);
4793 }
4794 
4795 /*@
4796    MatDuplicate - Duplicates a matrix including the non-zero structure.
4797 
4798    Collective
4799 
4800    Input Parameters:
4801 +  mat - the matrix
4802 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4803         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4804 
4805    Output Parameter:
4806 .  M - pointer to place new matrix
4807 
4808    Level: intermediate
4809 
4810    Notes:
4811     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4812 
4813     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.
4814 
4815     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
4816     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4817     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4818 
4819 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4820 @*/
4821 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4822 {
4823   Mat         B;
4824   VecType     vtype;
4825   PetscInt    i;
4826   PetscObject dm;
4827   void (*viewf)(void);
4828 
4829   PetscFunctionBegin;
4830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4831   PetscValidType(mat, 1);
4832   PetscValidPointer(M, 3);
4833   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4834   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4835   MatCheckPreallocated(mat, 1);
4836 
4837   *M = NULL;
4838   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4839   PetscUseTypeMethod(mat, duplicate, op, M);
4840   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4841   B = *M;
4842 
4843   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4844   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4845   PetscCall(MatGetVecType(mat, &vtype));
4846   PetscCall(MatSetVecType(B, vtype));
4847 
4848   B->stencil.dim = mat->stencil.dim;
4849   B->stencil.noc = mat->stencil.noc;
4850   for (i = 0; i <= mat->stencil.dim; i++) {
4851     B->stencil.dims[i]   = mat->stencil.dims[i];
4852     B->stencil.starts[i] = mat->stencil.starts[i];
4853   }
4854 
4855   B->nooffproczerorows = mat->nooffproczerorows;
4856   B->nooffprocentries  = mat->nooffprocentries;
4857 
4858   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4859   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4860   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4861   PetscFunctionReturn(PETSC_SUCCESS);
4862 }
4863 
4864 /*@
4865    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4866 
4867    Logically Collective
4868 
4869    Input Parameter:
4870 .  mat - the matrix
4871 
4872    Output Parameter:
4873 .  v - the diagonal of the matrix
4874 
4875    Level: intermediate
4876 
4877    Note:
4878    Currently only correct in parallel for square matrices.
4879 
4880 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4881 @*/
4882 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4883 {
4884   PetscFunctionBegin;
4885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4886   PetscValidType(mat, 1);
4887   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4888   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4889   MatCheckPreallocated(mat, 1);
4890 
4891   PetscUseTypeMethod(mat, getdiagonal, v);
4892   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4893   PetscFunctionReturn(PETSC_SUCCESS);
4894 }
4895 
4896 /*@C
4897    MatGetRowMin - Gets the minimum value (of the real part) of each
4898         row of the matrix
4899 
4900    Logically Collective
4901 
4902    Input Parameter:
4903 .  mat - the matrix
4904 
4905    Output Parameters:
4906 +  v - the vector for storing the maximums
4907 -  idx - the indices of the column found for each row (optional)
4908 
4909    Level: intermediate
4910 
4911    Note:
4912     The result of this call are the same as if one converted the matrix to dense format
4913       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4914 
4915     This code is only implemented for a couple of matrix formats.
4916 
4917 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4918           `MatGetRowMax()`
4919 @*/
4920 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4921 {
4922   PetscFunctionBegin;
4923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4924   PetscValidType(mat, 1);
4925   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4926   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4927 
4928   if (!mat->cmap->N) {
4929     PetscCall(VecSet(v, PETSC_MAX_REAL));
4930     if (idx) {
4931       PetscInt i, m = mat->rmap->n;
4932       for (i = 0; i < m; i++) idx[i] = -1;
4933     }
4934   } else {
4935     MatCheckPreallocated(mat, 1);
4936   }
4937   PetscUseTypeMethod(mat, getrowmin, v, idx);
4938   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4939   PetscFunctionReturn(PETSC_SUCCESS);
4940 }
4941 
4942 /*@C
4943    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4944         row of the matrix
4945 
4946    Logically Collective
4947 
4948    Input Parameter:
4949 .  mat - the matrix
4950 
4951    Output Parameters:
4952 +  v - the vector for storing the minimums
4953 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4954 
4955    Level: intermediate
4956 
4957    Notes:
4958     if a row is completely empty or has only 0.0 values then the idx[] value for that
4959     row is 0 (the first column).
4960 
4961     This code is only implemented for a couple of matrix formats.
4962 
4963 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4964 @*/
4965 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4966 {
4967   PetscFunctionBegin;
4968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4969   PetscValidType(mat, 1);
4970   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4971   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4972   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4973 
4974   if (!mat->cmap->N) {
4975     PetscCall(VecSet(v, 0.0));
4976     if (idx) {
4977       PetscInt i, m = mat->rmap->n;
4978       for (i = 0; i < m; i++) idx[i] = -1;
4979     }
4980   } else {
4981     MatCheckPreallocated(mat, 1);
4982     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4983     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4984   }
4985   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4986   PetscFunctionReturn(PETSC_SUCCESS);
4987 }
4988 
4989 /*@C
4990    MatGetRowMax - Gets the maximum value (of the real part) of each
4991         row of the matrix
4992 
4993    Logically Collective
4994 
4995    Input Parameter:
4996 .  mat - the matrix
4997 
4998    Output Parameters:
4999 +  v - the vector for storing the maximums
5000 -  idx - the indices of the column found for each row (optional)
5001 
5002    Level: intermediate
5003 
5004    Notes:
5005     The result of this call are the same as if one converted the matrix to dense format
5006       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5007 
5008     This code is only implemented for a couple of matrix formats.
5009 
5010 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5011 @*/
5012 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5013 {
5014   PetscFunctionBegin;
5015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5016   PetscValidType(mat, 1);
5017   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5018   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5019 
5020   if (!mat->cmap->N) {
5021     PetscCall(VecSet(v, PETSC_MIN_REAL));
5022     if (idx) {
5023       PetscInt i, m = mat->rmap->n;
5024       for (i = 0; i < m; i++) idx[i] = -1;
5025     }
5026   } else {
5027     MatCheckPreallocated(mat, 1);
5028     PetscUseTypeMethod(mat, getrowmax, v, idx);
5029   }
5030   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5031   PetscFunctionReturn(PETSC_SUCCESS);
5032 }
5033 
5034 /*@C
5035    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5036         row of the matrix
5037 
5038    Logically Collective
5039 
5040    Input Parameter:
5041 .  mat - the matrix
5042 
5043    Output Parameters:
5044 +  v - the vector for storing the maximums
5045 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5046 
5047    Level: intermediate
5048 
5049    Notes:
5050     if a row is completely empty or has only 0.0 values then the idx[] value for that
5051     row is 0 (the first column).
5052 
5053     This code is only implemented for a couple of matrix formats.
5054 
5055 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5056 @*/
5057 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5058 {
5059   PetscFunctionBegin;
5060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5061   PetscValidType(mat, 1);
5062   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5063   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5064 
5065   if (!mat->cmap->N) {
5066     PetscCall(VecSet(v, 0.0));
5067     if (idx) {
5068       PetscInt i, m = mat->rmap->n;
5069       for (i = 0; i < m; i++) idx[i] = -1;
5070     }
5071   } else {
5072     MatCheckPreallocated(mat, 1);
5073     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5074     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5075   }
5076   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5077   PetscFunctionReturn(PETSC_SUCCESS);
5078 }
5079 
5080 /*@
5081    MatGetRowSum - Gets the sum of each row of the matrix
5082 
5083    Logically or Neighborhood Collective
5084 
5085    Input Parameter:
5086 .  mat - the matrix
5087 
5088    Output Parameter:
5089 .  v - the vector for storing the sum of rows
5090 
5091    Level: intermediate
5092 
5093    Notes:
5094     This code is slow since it is not currently specialized for different formats
5095 
5096 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5097 @*/
5098 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5099 {
5100   Vec ones;
5101 
5102   PetscFunctionBegin;
5103   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5104   PetscValidType(mat, 1);
5105   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5106   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5107   MatCheckPreallocated(mat, 1);
5108   PetscCall(MatCreateVecs(mat, &ones, NULL));
5109   PetscCall(VecSet(ones, 1.));
5110   PetscCall(MatMult(mat, ones, v));
5111   PetscCall(VecDestroy(&ones));
5112   PetscFunctionReturn(PETSC_SUCCESS);
5113 }
5114 
5115 /*@
5116    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5117    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5118 
5119    Collective
5120 
5121    Input Parameter:
5122 .  mat - the matrix to provide the transpose
5123 
5124    Output Parameter:
5125 .  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
5126 
5127    Level: advanced
5128 
5129    Note:
5130    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
5131    routine allows bypassing that call.
5132 
5133 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5134 @*/
5135 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5136 {
5137   PetscContainer  rB = NULL;
5138   MatParentState *rb = NULL;
5139 
5140   PetscFunctionBegin;
5141   PetscCall(PetscNew(&rb));
5142   rb->id    = ((PetscObject)mat)->id;
5143   rb->state = 0;
5144   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5145   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5146   PetscCall(PetscContainerSetPointer(rB, rb));
5147   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5148   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5149   PetscCall(PetscObjectDereference((PetscObject)rB));
5150   PetscFunctionReturn(PETSC_SUCCESS);
5151 }
5152 
5153 /*@
5154    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5155 
5156    Collective
5157 
5158    Input Parameters:
5159 +  mat - the matrix to transpose
5160 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5161 
5162    Output Parameter:
5163 .  B - the transpose
5164 
5165    Level: intermediate
5166 
5167    Notes:
5168      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5169 
5170      `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
5171      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5172 
5173      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.
5174 
5175      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5176 
5177      If mat is unchanged from the last call this function returns immediately without recomputing the result
5178 
5179      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5180 
5181 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5182           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5183 @*/
5184 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5185 {
5186   PetscContainer  rB = NULL;
5187   MatParentState *rb = NULL;
5188 
5189   PetscFunctionBegin;
5190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5191   PetscValidType(mat, 1);
5192   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5193   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5194   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5195   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5196   MatCheckPreallocated(mat, 1);
5197   if (reuse == MAT_REUSE_MATRIX) {
5198     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5199     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5200     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5201     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5202     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5203   }
5204 
5205   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5206   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5207     PetscUseTypeMethod(mat, transpose, reuse, B);
5208     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5209   }
5210   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5211 
5212   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5213   if (reuse != MAT_INPLACE_MATRIX) {
5214     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5215     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5216     rb->state        = ((PetscObject)mat)->state;
5217     rb->nonzerostate = mat->nonzerostate;
5218   }
5219   PetscFunctionReturn(PETSC_SUCCESS);
5220 }
5221 
5222 /*@
5223    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5224 
5225    Collective
5226 
5227    Input Parameter:
5228 .  A - the matrix to transpose
5229 
5230    Output Parameter:
5231 .  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
5232       numerical portion.
5233 
5234    Level: intermediate
5235 
5236    Note:
5237    This is not supported for many matrix types, use `MatTranspose()` in those cases
5238 
5239 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5240 @*/
5241 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5242 {
5243   PetscFunctionBegin;
5244   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5245   PetscValidType(A, 1);
5246   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5247   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5248   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5249   PetscUseTypeMethod(A, transposesymbolic, B);
5250   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5251 
5252   PetscCall(MatTransposeSetPrecursor(A, *B));
5253   PetscFunctionReturn(PETSC_SUCCESS);
5254 }
5255 
5256 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5257 {
5258   PetscContainer  rB;
5259   MatParentState *rb;
5260 
5261   PetscFunctionBegin;
5262   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5263   PetscValidType(A, 1);
5264   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5265   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5266   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5267   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5268   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5269   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5270   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5271   PetscFunctionReturn(PETSC_SUCCESS);
5272 }
5273 
5274 /*@
5275    MatIsTranspose - Test whether a matrix is another one's transpose,
5276         or its own, in which case it tests symmetry.
5277 
5278    Collective
5279 
5280    Input Parameters:
5281 +  A - the matrix to test
5282 .  B - the matrix to test against, this can equal the first parameter
5283 -  tol - tolerance, differences between entries smaller than this are counted as zero
5284 
5285    Output Parameter:
5286 .  flg - the result
5287 
5288    Level: intermediate
5289 
5290    Notes:
5291    Only available for `MATAIJ` matrices.
5292 
5293    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5294    test involves parallel copies of the block-offdiagonal parts of the matrix.
5295 
5296 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5297 @*/
5298 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5299 {
5300   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5301 
5302   PetscFunctionBegin;
5303   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5304   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5305   PetscValidBoolPointer(flg, 4);
5306   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5307   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5308   *flg = PETSC_FALSE;
5309   if (f && g) {
5310     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5311     PetscCall((*f)(A, B, tol, flg));
5312   } else {
5313     MatType mattype;
5314 
5315     PetscCall(MatGetType(f ? B : A, &mattype));
5316     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5317   }
5318   PetscFunctionReturn(PETSC_SUCCESS);
5319 }
5320 
5321 /*@
5322    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5323 
5324    Collective
5325 
5326    Input Parameters:
5327 +  mat - the matrix to transpose and complex conjugate
5328 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5329 
5330    Output Parameter:
5331 .  B - the Hermitian transpose
5332 
5333    Level: intermediate
5334 
5335 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5336 @*/
5337 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5338 {
5339   PetscFunctionBegin;
5340   PetscCall(MatTranspose(mat, reuse, B));
5341 #if defined(PETSC_USE_COMPLEX)
5342   PetscCall(MatConjugate(*B));
5343 #endif
5344   PetscFunctionReturn(PETSC_SUCCESS);
5345 }
5346 
5347 /*@
5348    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5349 
5350    Collective
5351 
5352    Input Parameters:
5353 +  A - the matrix to test
5354 .  B - the matrix to test against, this can equal the first parameter
5355 -  tol - tolerance, differences between entries smaller than this are counted as zero
5356 
5357    Output Parameter:
5358 .  flg - the result
5359 
5360    Level: intermediate
5361 
5362    Notes:
5363    Only available for `MATAIJ` matrices.
5364 
5365    The sequential algorithm
5366    has a running time of the order of the number of nonzeros; the parallel
5367    test involves parallel copies of the block-offdiagonal parts of the matrix.
5368 
5369 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5370 @*/
5371 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5372 {
5373   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5374 
5375   PetscFunctionBegin;
5376   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5377   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5378   PetscValidBoolPointer(flg, 4);
5379   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5380   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5381   if (f && g) {
5382     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5383     PetscCall((*f)(A, B, tol, flg));
5384   }
5385   PetscFunctionReturn(PETSC_SUCCESS);
5386 }
5387 
5388 /*@
5389    MatPermute - Creates a new matrix with rows and columns permuted from the
5390    original.
5391 
5392    Collective
5393 
5394    Input Parameters:
5395 +  mat - the matrix to permute
5396 .  row - row permutation, each processor supplies only the permutation for its rows
5397 -  col - column permutation, each processor supplies only the permutation for its columns
5398 
5399    Output Parameter:
5400 .  B - the permuted matrix
5401 
5402    Level: advanced
5403 
5404    Note:
5405    The index sets map from row/col of permuted matrix to row/col of original matrix.
5406    The index sets should be on the same communicator as mat and have the same local sizes.
5407 
5408    Developer Note:
5409      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5410      exploit the fact that row and col are permutations, consider implementing the
5411      more general `MatCreateSubMatrix()` instead.
5412 
5413 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5414 @*/
5415 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5416 {
5417   PetscFunctionBegin;
5418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5419   PetscValidType(mat, 1);
5420   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5421   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5422   PetscValidPointer(B, 4);
5423   PetscCheckSameComm(mat, 1, row, 2);
5424   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5425   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5426   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5427   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5428   MatCheckPreallocated(mat, 1);
5429 
5430   if (mat->ops->permute) {
5431     PetscUseTypeMethod(mat, permute, row, col, B);
5432     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5433   } else {
5434     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5435   }
5436   PetscFunctionReturn(PETSC_SUCCESS);
5437 }
5438 
5439 /*@
5440    MatEqual - Compares two matrices.
5441 
5442    Collective
5443 
5444    Input Parameters:
5445 +  A - the first matrix
5446 -  B - the second matrix
5447 
5448    Output Parameter:
5449 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5450 
5451    Level: intermediate
5452 
5453 .seealso: [](chapter_matrices), `Mat`
5454 @*/
5455 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5456 {
5457   PetscFunctionBegin;
5458   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5459   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5460   PetscValidType(A, 1);
5461   PetscValidType(B, 2);
5462   PetscValidBoolPointer(flg, 3);
5463   PetscCheckSameComm(A, 1, B, 2);
5464   MatCheckPreallocated(A, 1);
5465   MatCheckPreallocated(B, 2);
5466   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5467   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5468   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,
5469              B->cmap->N);
5470   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5471     PetscUseTypeMethod(A, equal, B, flg);
5472   } else {
5473     PetscCall(MatMultEqual(A, B, 10, flg));
5474   }
5475   PetscFunctionReturn(PETSC_SUCCESS);
5476 }
5477 
5478 /*@
5479    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5480    matrices that are stored as vectors.  Either of the two scaling
5481    matrices can be `NULL`.
5482 
5483    Collective
5484 
5485    Input Parameters:
5486 +  mat - the matrix to be scaled
5487 .  l - the left scaling vector (or `NULL`)
5488 -  r - the right scaling vector (or `NULL`)
5489 
5490    Level: intermediate
5491 
5492    Note:
5493    `MatDiagonalScale()` computes A = LAR, where
5494    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5495    The L scales the rows of the matrix, the R scales the columns of the matrix.
5496 
5497 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5498 @*/
5499 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5500 {
5501   PetscFunctionBegin;
5502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5503   PetscValidType(mat, 1);
5504   if (l) {
5505     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5506     PetscCheckSameComm(mat, 1, l, 2);
5507   }
5508   if (r) {
5509     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5510     PetscCheckSameComm(mat, 1, r, 3);
5511   }
5512   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5513   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5514   MatCheckPreallocated(mat, 1);
5515   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5516 
5517   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5518   PetscUseTypeMethod(mat, diagonalscale, l, r);
5519   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5520   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5521   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5522   PetscFunctionReturn(PETSC_SUCCESS);
5523 }
5524 
5525 /*@
5526     MatScale - Scales all elements of a matrix by a given number.
5527 
5528     Logically Collective
5529 
5530     Input Parameters:
5531 +   mat - the matrix to be scaled
5532 -   a  - the scaling value
5533 
5534     Level: intermediate
5535 
5536 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5537 @*/
5538 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5539 {
5540   PetscFunctionBegin;
5541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5542   PetscValidType(mat, 1);
5543   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5544   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5545   PetscValidLogicalCollectiveScalar(mat, a, 2);
5546   MatCheckPreallocated(mat, 1);
5547 
5548   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5549   if (a != (PetscScalar)1.0) {
5550     PetscUseTypeMethod(mat, scale, a);
5551     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5552   }
5553   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5554   PetscFunctionReturn(PETSC_SUCCESS);
5555 }
5556 
5557 /*@
5558    MatNorm - Calculates various norms of a matrix.
5559 
5560    Collective
5561 
5562    Input Parameters:
5563 +  mat - the matrix
5564 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5565 
5566    Output Parameter:
5567 .  nrm - the resulting norm
5568 
5569    Level: intermediate
5570 
5571 .seealso: [](chapter_matrices), `Mat`
5572 @*/
5573 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5574 {
5575   PetscFunctionBegin;
5576   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5577   PetscValidType(mat, 1);
5578   PetscValidRealPointer(nrm, 3);
5579 
5580   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5581   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5582   MatCheckPreallocated(mat, 1);
5583 
5584   PetscUseTypeMethod(mat, norm, type, nrm);
5585   PetscFunctionReturn(PETSC_SUCCESS);
5586 }
5587 
5588 /*
5589      This variable is used to prevent counting of MatAssemblyBegin() that
5590    are called from within a MatAssemblyEnd().
5591 */
5592 static PetscInt MatAssemblyEnd_InUse = 0;
5593 /*@
5594    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5595    be called after completing all calls to `MatSetValues()`.
5596 
5597    Collective
5598 
5599    Input Parameters:
5600 +  mat - the matrix
5601 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5602 
5603    Level: beginner
5604 
5605    Notes:
5606    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5607    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5608 
5609    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5610    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5611    using the matrix.
5612 
5613    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5614    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
5615    a global collective operation requiring all processes that share the matrix.
5616 
5617    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5618    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5619    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5620 
5621 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5622 @*/
5623 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5624 {
5625   PetscFunctionBegin;
5626   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5627   PetscValidType(mat, 1);
5628   MatCheckPreallocated(mat, 1);
5629   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5630   if (mat->assembled) {
5631     mat->was_assembled = PETSC_TRUE;
5632     mat->assembled     = PETSC_FALSE;
5633   }
5634 
5635   if (!MatAssemblyEnd_InUse) {
5636     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5637     PetscTryTypeMethod(mat, assemblybegin, type);
5638     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5639   } else PetscTryTypeMethod(mat, assemblybegin, type);
5640   PetscFunctionReturn(PETSC_SUCCESS);
5641 }
5642 
5643 /*@
5644    MatAssembled - Indicates if a matrix has been assembled and is ready for
5645      use; for example, in matrix-vector product.
5646 
5647    Not Collective
5648 
5649    Input Parameter:
5650 .  mat - the matrix
5651 
5652    Output Parameter:
5653 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5654 
5655    Level: advanced
5656 
5657 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5658 @*/
5659 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5660 {
5661   PetscFunctionBegin;
5662   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5663   PetscValidBoolPointer(assembled, 2);
5664   *assembled = mat->assembled;
5665   PetscFunctionReturn(PETSC_SUCCESS);
5666 }
5667 
5668 /*@
5669    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5670    be called after `MatAssemblyBegin()`.
5671 
5672    Collective
5673 
5674    Input Parameters:
5675 +  mat - the matrix
5676 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5677 
5678    Options Database Keys:
5679 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5680 .  -mat_view ::ascii_info_detail - Prints more detailed info
5681 .  -mat_view - Prints matrix in ASCII format
5682 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5683 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5684 .  -display <name> - Sets display name (default is host)
5685 .  -draw_pause <sec> - Sets number of seconds to pause after display
5686 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5687 .  -viewer_socket_machine <machine> - Machine to use for socket
5688 .  -viewer_socket_port <port> - Port number to use for socket
5689 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5690 
5691    Level: beginner
5692 
5693 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5694 @*/
5695 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5696 {
5697   static PetscInt inassm = 0;
5698   PetscBool       flg    = PETSC_FALSE;
5699 
5700   PetscFunctionBegin;
5701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5702   PetscValidType(mat, 1);
5703 
5704   inassm++;
5705   MatAssemblyEnd_InUse++;
5706   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5707     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5708     PetscTryTypeMethod(mat, assemblyend, type);
5709     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5710   } else PetscTryTypeMethod(mat, assemblyend, type);
5711 
5712   /* Flush assembly is not a true assembly */
5713   if (type != MAT_FLUSH_ASSEMBLY) {
5714     if (mat->num_ass) {
5715       if (!mat->symmetry_eternal) {
5716         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5717         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5718       }
5719       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5720       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5721     }
5722     mat->num_ass++;
5723     mat->assembled        = PETSC_TRUE;
5724     mat->ass_nonzerostate = mat->nonzerostate;
5725   }
5726 
5727   mat->insertmode = NOT_SET_VALUES;
5728   MatAssemblyEnd_InUse--;
5729   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5730   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5731     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5732 
5733     if (mat->checksymmetryonassembly) {
5734       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5735       if (flg) {
5736         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5737       } else {
5738         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5739       }
5740     }
5741     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5742   }
5743   inassm--;
5744   PetscFunctionReturn(PETSC_SUCCESS);
5745 }
5746 
5747 /*@
5748    MatSetOption - Sets a parameter option for a matrix. Some options
5749    may be specific to certain storage formats.  Some options
5750    determine how values will be inserted (or added). Sorted,
5751    row-oriented input will generally assemble the fastest. The default
5752    is row-oriented.
5753 
5754    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5755 
5756    Input Parameters:
5757 +  mat - the matrix
5758 .  option - the option, one of those listed below (and possibly others),
5759 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5760 
5761   Options Describing Matrix Structure:
5762 +    `MAT_SPD` - symmetric positive definite
5763 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5764 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5765 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5766 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5767 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5768 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5769 
5770    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5771    do not need to be computed (usually at a high cost)
5772 
5773    Options For Use with `MatSetValues()`:
5774    Insert a logically dense subblock, which can be
5775 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5776 
5777    These options reflect the data you pass in with `MatSetValues()`; it has
5778    nothing to do with how the data is stored internally in the matrix
5779    data structure.
5780 
5781    When (re)assembling a matrix, we can restrict the input for
5782    efficiency/debugging purposes.  These options include
5783 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5784 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5785 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5786 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5787 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5788 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5789         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5790         performance for very large process counts.
5791 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5792         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5793         functions, instead sending only neighbor messages.
5794 
5795    Level: intermediate
5796 
5797    Notes:
5798    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5799 
5800    Some options are relevant only for particular matrix types and
5801    are thus ignored by others.  Other options are not supported by
5802    certain matrix types and will generate an error message if set.
5803 
5804    If using Fortran to compute a matrix, one may need to
5805    use the column-oriented option (or convert to the row-oriented
5806    format).
5807 
5808    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5809    that would generate a new entry in the nonzero structure is instead
5810    ignored.  Thus, if memory has not already been allocated for this particular
5811    data, then the insertion is ignored. For dense matrices, in which
5812    the entire array is allocated, no entries are ever ignored.
5813    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5814 
5815    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5816    that would generate a new entry in the nonzero structure instead produces
5817    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
5818 
5819    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5820    that would generate a new entry that has not been preallocated will
5821    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5822    only.) This is a useful flag when debugging matrix memory preallocation.
5823    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5824 
5825    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5826    other processors should be dropped, rather than stashed.
5827    This is useful if you know that the "owning" processor is also
5828    always generating the correct matrix entries, so that PETSc need
5829    not transfer duplicate entries generated on another processor.
5830 
5831    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5832    searches during matrix assembly. When this flag is set, the hash table
5833    is created during the first matrix assembly. This hash table is
5834    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5835    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5836    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5837    supported by `MATMPIBAIJ` format only.
5838 
5839    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5840    are kept in the nonzero structure
5841 
5842    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5843    a zero location in the matrix
5844 
5845    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5846 
5847    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5848         zero row routines and thus improves performance for very large process counts.
5849 
5850    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5851         part of the matrix (since they should match the upper triangular part).
5852 
5853    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5854                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5855                      with finite difference schemes with non-periodic boundary conditions.
5856 
5857    Developer Note:
5858    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5859    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5860    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5861    not changed.
5862 
5863 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5864 @*/
5865 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5866 {
5867   PetscFunctionBegin;
5868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5869   if (op > 0) {
5870     PetscValidLogicalCollectiveEnum(mat, op, 2);
5871     PetscValidLogicalCollectiveBool(mat, flg, 3);
5872   }
5873 
5874   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);
5875 
5876   switch (op) {
5877   case MAT_FORCE_DIAGONAL_ENTRIES:
5878     mat->force_diagonals = flg;
5879     PetscFunctionReturn(PETSC_SUCCESS);
5880   case MAT_NO_OFF_PROC_ENTRIES:
5881     mat->nooffprocentries = flg;
5882     PetscFunctionReturn(PETSC_SUCCESS);
5883   case MAT_SUBSET_OFF_PROC_ENTRIES:
5884     mat->assembly_subset = flg;
5885     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5886 #if !defined(PETSC_HAVE_MPIUNI)
5887       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5888 #endif
5889       mat->stash.first_assembly_done = PETSC_FALSE;
5890     }
5891     PetscFunctionReturn(PETSC_SUCCESS);
5892   case MAT_NO_OFF_PROC_ZERO_ROWS:
5893     mat->nooffproczerorows = flg;
5894     PetscFunctionReturn(PETSC_SUCCESS);
5895   case MAT_SPD:
5896     if (flg) {
5897       mat->spd                    = PETSC_BOOL3_TRUE;
5898       mat->symmetric              = PETSC_BOOL3_TRUE;
5899       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5900     } else {
5901       mat->spd = PETSC_BOOL3_FALSE;
5902     }
5903     break;
5904   case MAT_SYMMETRIC:
5905     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5906     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5907 #if !defined(PETSC_USE_COMPLEX)
5908     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5909 #endif
5910     break;
5911   case MAT_HERMITIAN:
5912     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5913     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5914 #if !defined(PETSC_USE_COMPLEX)
5915     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5916 #endif
5917     break;
5918   case MAT_STRUCTURALLY_SYMMETRIC:
5919     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5920     break;
5921   case MAT_SYMMETRY_ETERNAL:
5922     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");
5923     mat->symmetry_eternal = flg;
5924     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5925     break;
5926   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5927     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");
5928     mat->structural_symmetry_eternal = flg;
5929     break;
5930   case MAT_SPD_ETERNAL:
5931     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");
5932     mat->spd_eternal = flg;
5933     if (flg) {
5934       mat->structural_symmetry_eternal = PETSC_TRUE;
5935       mat->symmetry_eternal            = PETSC_TRUE;
5936     }
5937     break;
5938   case MAT_STRUCTURE_ONLY:
5939     mat->structure_only = flg;
5940     break;
5941   case MAT_SORTED_FULL:
5942     mat->sortedfull = flg;
5943     break;
5944   default:
5945     break;
5946   }
5947   PetscTryTypeMethod(mat, setoption, op, flg);
5948   PetscFunctionReturn(PETSC_SUCCESS);
5949 }
5950 
5951 /*@
5952    MatGetOption - Gets a parameter option that has been set for a matrix.
5953 
5954    Logically Collective
5955 
5956    Input Parameters:
5957 +  mat - the matrix
5958 -  option - the option, this only responds to certain options, check the code for which ones
5959 
5960    Output Parameter:
5961 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5962 
5963    Level: intermediate
5964 
5965     Notes:
5966     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5967 
5968     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5969     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5970 
5971 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5972     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5973 @*/
5974 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5975 {
5976   PetscFunctionBegin;
5977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5978   PetscValidType(mat, 1);
5979 
5980   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);
5981   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()");
5982 
5983   switch (op) {
5984   case MAT_NO_OFF_PROC_ENTRIES:
5985     *flg = mat->nooffprocentries;
5986     break;
5987   case MAT_NO_OFF_PROC_ZERO_ROWS:
5988     *flg = mat->nooffproczerorows;
5989     break;
5990   case MAT_SYMMETRIC:
5991     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5992     break;
5993   case MAT_HERMITIAN:
5994     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
5995     break;
5996   case MAT_STRUCTURALLY_SYMMETRIC:
5997     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
5998     break;
5999   case MAT_SPD:
6000     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6001     break;
6002   case MAT_SYMMETRY_ETERNAL:
6003     *flg = mat->symmetry_eternal;
6004     break;
6005   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6006     *flg = mat->symmetry_eternal;
6007     break;
6008   default:
6009     break;
6010   }
6011   PetscFunctionReturn(PETSC_SUCCESS);
6012 }
6013 
6014 /*@
6015    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6016    this routine retains the old nonzero structure.
6017 
6018    Logically Collective
6019 
6020    Input Parameter:
6021 .  mat - the matrix
6022 
6023    Level: intermediate
6024 
6025    Note:
6026     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.
6027    See the Performance chapter of the users manual for information on preallocating matrices.
6028 
6029 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6030 @*/
6031 PetscErrorCode MatZeroEntries(Mat mat)
6032 {
6033   PetscFunctionBegin;
6034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6035   PetscValidType(mat, 1);
6036   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6037   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");
6038   MatCheckPreallocated(mat, 1);
6039 
6040   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6041   PetscUseTypeMethod(mat, zeroentries);
6042   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6043   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6044   PetscFunctionReturn(PETSC_SUCCESS);
6045 }
6046 
6047 /*@
6048    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6049    of a set of rows and columns of a matrix.
6050 
6051    Collective
6052 
6053    Input Parameters:
6054 +  mat - the matrix
6055 .  numRows - the number of rows/columns to zero
6056 .  rows - the global row indices
6057 .  diag - value put in the diagonal of the eliminated rows
6058 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6059 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6060 
6061    Level: intermediate
6062 
6063    Notes:
6064    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6065 
6066    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6067    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
6068 
6069    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6070    Krylov method to take advantage of the known solution on the zeroed rows.
6071 
6072    For the parallel case, all processes that share the matrix (i.e.,
6073    those in the communicator used for matrix creation) MUST call this
6074    routine, regardless of whether any rows being zeroed are owned by
6075    them.
6076 
6077    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6078 
6079    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6080    list only rows local to itself).
6081 
6082    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6083 
6084 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6085           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6086 @*/
6087 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6088 {
6089   PetscFunctionBegin;
6090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6091   PetscValidType(mat, 1);
6092   if (numRows) PetscValidIntPointer(rows, 3);
6093   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6094   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6095   MatCheckPreallocated(mat, 1);
6096 
6097   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6098   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6099   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6100   PetscFunctionReturn(PETSC_SUCCESS);
6101 }
6102 
6103 /*@
6104    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6105    of a set of rows and columns of a matrix.
6106 
6107    Collective
6108 
6109    Input Parameters:
6110 +  mat - the matrix
6111 .  is - the rows to zero
6112 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6113 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6114 -  b - optional vector of right hand side, that will be adjusted by provided solution
6115 
6116    Level: intermediate
6117 
6118    Note:
6119    See `MatZeroRowsColumns()` for details on how this routine operates.
6120 
6121 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6122           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6123 @*/
6124 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6125 {
6126   PetscInt        numRows;
6127   const PetscInt *rows;
6128 
6129   PetscFunctionBegin;
6130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6131   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6132   PetscValidType(mat, 1);
6133   PetscValidType(is, 2);
6134   PetscCall(ISGetLocalSize(is, &numRows));
6135   PetscCall(ISGetIndices(is, &rows));
6136   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6137   PetscCall(ISRestoreIndices(is, &rows));
6138   PetscFunctionReturn(PETSC_SUCCESS);
6139 }
6140 
6141 /*@
6142    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6143    of a set of rows of a matrix.
6144 
6145    Collective
6146 
6147    Input Parameters:
6148 +  mat - the matrix
6149 .  numRows - the number of rows to zero
6150 .  rows - the global row indices
6151 .  diag - value put in the diagonal of the zeroed rows
6152 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6153 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6154 
6155    Level: intermediate
6156 
6157    Notes:
6158    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6159 
6160    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6161 
6162    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6163    Krylov method to take advantage of the known solution on the zeroed rows.
6164 
6165    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)
6166    from the matrix.
6167 
6168    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6169    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
6170    formats this does not alter the nonzero structure.
6171 
6172    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6173    of the matrix is not changed the values are
6174    merely zeroed.
6175 
6176    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6177    formats can optionally remove the main diagonal entry from the
6178    nonzero structure as well, by passing 0.0 as the final argument).
6179 
6180    For the parallel case, all processes that share the matrix (i.e.,
6181    those in the communicator used for matrix creation) MUST call this
6182    routine, regardless of whether any rows being zeroed are owned by
6183    them.
6184 
6185    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6186    list only rows local to itself).
6187 
6188    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6189    owns that are to be zeroed. This saves a global synchronization in the implementation.
6190 
6191 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6192           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6193 @*/
6194 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6195 {
6196   PetscFunctionBegin;
6197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6198   PetscValidType(mat, 1);
6199   if (numRows) PetscValidIntPointer(rows, 3);
6200   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6201   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6202   MatCheckPreallocated(mat, 1);
6203 
6204   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6205   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6206   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6207   PetscFunctionReturn(PETSC_SUCCESS);
6208 }
6209 
6210 /*@
6211    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6212    of a set of rows of a matrix.
6213 
6214    Collective
6215 
6216    Input Parameters:
6217 +  mat - the matrix
6218 .  is - index set of rows to remove (if `NULL` then no row is removed)
6219 .  diag - value put in all diagonals of eliminated rows
6220 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6221 -  b - optional vector of right hand side, that will be adjusted by provided solution
6222 
6223    Level: intermediate
6224 
6225    Note:
6226    See `MatZeroRows()` for details on how this routine operates.
6227 
6228 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6229           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6230 @*/
6231 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6232 {
6233   PetscInt        numRows = 0;
6234   const PetscInt *rows    = NULL;
6235 
6236   PetscFunctionBegin;
6237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6238   PetscValidType(mat, 1);
6239   if (is) {
6240     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6241     PetscCall(ISGetLocalSize(is, &numRows));
6242     PetscCall(ISGetIndices(is, &rows));
6243   }
6244   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6245   if (is) PetscCall(ISRestoreIndices(is, &rows));
6246   PetscFunctionReturn(PETSC_SUCCESS);
6247 }
6248 
6249 /*@
6250    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6251    of a set of rows of a matrix. These rows must be local to the process.
6252 
6253    Collective
6254 
6255    Input Parameters:
6256 +  mat - the matrix
6257 .  numRows - the number of rows to remove
6258 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6259 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6260 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6261 -  b - optional vector of right hand side, that will be adjusted by provided solution
6262 
6263    Level: intermediate
6264 
6265    Notes:
6266    See `MatZeroRows()` for details on how this routine operates.
6267 
6268    The grid coordinates are across the entire grid, not just the local portion
6269 
6270    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6271    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6272    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6273    `DM_BOUNDARY_PERIODIC` boundary type.
6274 
6275    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
6276    a single value per point) you can skip filling those indices.
6277 
6278    Fortran Note:
6279    `idxm` and `idxn` should be declared as
6280 $     MatStencil idxm(4,m)
6281    and the values inserted using
6282 .vb
6283     idxm(MatStencil_i,1) = i
6284     idxm(MatStencil_j,1) = j
6285     idxm(MatStencil_k,1) = k
6286     idxm(MatStencil_c,1) = c
6287    etc
6288 .ve
6289 
6290 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6291           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6292 @*/
6293 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6294 {
6295   PetscInt  dim    = mat->stencil.dim;
6296   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6297   PetscInt *dims   = mat->stencil.dims + 1;
6298   PetscInt *starts = mat->stencil.starts;
6299   PetscInt *dxm    = (PetscInt *)rows;
6300   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6301 
6302   PetscFunctionBegin;
6303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6304   PetscValidType(mat, 1);
6305   if (numRows) PetscValidPointer(rows, 3);
6306 
6307   PetscCall(PetscMalloc1(numRows, &jdxm));
6308   for (i = 0; i < numRows; ++i) {
6309     /* Skip unused dimensions (they are ordered k, j, i, c) */
6310     for (j = 0; j < 3 - sdim; ++j) dxm++;
6311     /* Local index in X dir */
6312     tmp = *dxm++ - starts[0];
6313     /* Loop over remaining dimensions */
6314     for (j = 0; j < dim - 1; ++j) {
6315       /* If nonlocal, set index to be negative */
6316       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6317       /* Update local index */
6318       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6319     }
6320     /* Skip component slot if necessary */
6321     if (mat->stencil.noc) dxm++;
6322     /* Local row number */
6323     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6324   }
6325   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6326   PetscCall(PetscFree(jdxm));
6327   PetscFunctionReturn(PETSC_SUCCESS);
6328 }
6329 
6330 /*@
6331    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6332    of a set of rows and columns of a matrix.
6333 
6334    Collective
6335 
6336    Input Parameters:
6337 +  mat - the matrix
6338 .  numRows - the number of rows/columns to remove
6339 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6340 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6341 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6342 -  b - optional vector of right hand side, that will be adjusted by provided solution
6343 
6344    Level: intermediate
6345 
6346    Notes:
6347    See `MatZeroRowsColumns()` for details on how this routine operates.
6348 
6349    The grid coordinates are across the entire grid, not just the local portion
6350 
6351    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6352    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6353    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6354    `DM_BOUNDARY_PERIODIC` boundary type.
6355 
6356    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
6357    a single value per point) you can skip filling those indices.
6358 
6359    Fortran Note:
6360    `idxm` and `idxn` should be declared as
6361 $     MatStencil idxm(4,m)
6362    and the values inserted using
6363 .vb
6364     idxm(MatStencil_i,1) = i
6365     idxm(MatStencil_j,1) = j
6366     idxm(MatStencil_k,1) = k
6367     idxm(MatStencil_c,1) = c
6368     etc
6369 .ve
6370 
6371 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6372           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6373 @*/
6374 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6375 {
6376   PetscInt  dim    = mat->stencil.dim;
6377   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6378   PetscInt *dims   = mat->stencil.dims + 1;
6379   PetscInt *starts = mat->stencil.starts;
6380   PetscInt *dxm    = (PetscInt *)rows;
6381   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6382 
6383   PetscFunctionBegin;
6384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6385   PetscValidType(mat, 1);
6386   if (numRows) PetscValidPointer(rows, 3);
6387 
6388   PetscCall(PetscMalloc1(numRows, &jdxm));
6389   for (i = 0; i < numRows; ++i) {
6390     /* Skip unused dimensions (they are ordered k, j, i, c) */
6391     for (j = 0; j < 3 - sdim; ++j) dxm++;
6392     /* Local index in X dir */
6393     tmp = *dxm++ - starts[0];
6394     /* Loop over remaining dimensions */
6395     for (j = 0; j < dim - 1; ++j) {
6396       /* If nonlocal, set index to be negative */
6397       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6398       /* Update local index */
6399       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6400     }
6401     /* Skip component slot if necessary */
6402     if (mat->stencil.noc) dxm++;
6403     /* Local row number */
6404     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6405   }
6406   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6407   PetscCall(PetscFree(jdxm));
6408   PetscFunctionReturn(PETSC_SUCCESS);
6409 }
6410 
6411 /*@C
6412    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6413    of a set of rows of a matrix; using local numbering of rows.
6414 
6415    Collective
6416 
6417    Input Parameters:
6418 +  mat - the matrix
6419 .  numRows - the number of rows to remove
6420 .  rows - the local row indices
6421 .  diag - value put in all diagonals of eliminated rows
6422 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6423 -  b - optional vector of right hand side, that will be adjusted by provided solution
6424 
6425    Level: intermediate
6426 
6427    Notes:
6428    Before calling `MatZeroRowsLocal()`, the user must first set the
6429    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6430 
6431    See `MatZeroRows()` for details on how this routine operates.
6432 
6433 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6434           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6435 @*/
6436 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6437 {
6438   PetscFunctionBegin;
6439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6440   PetscValidType(mat, 1);
6441   if (numRows) PetscValidIntPointer(rows, 3);
6442   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6443   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6444   MatCheckPreallocated(mat, 1);
6445 
6446   if (mat->ops->zerorowslocal) {
6447     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6448   } else {
6449     IS              is, newis;
6450     const PetscInt *newRows;
6451 
6452     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6453     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6454     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6455     PetscCall(ISGetIndices(newis, &newRows));
6456     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6457     PetscCall(ISRestoreIndices(newis, &newRows));
6458     PetscCall(ISDestroy(&newis));
6459     PetscCall(ISDestroy(&is));
6460   }
6461   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6462   PetscFunctionReturn(PETSC_SUCCESS);
6463 }
6464 
6465 /*@
6466    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6467    of a set of rows of a matrix; using local numbering of rows.
6468 
6469    Collective
6470 
6471    Input Parameters:
6472 +  mat - the matrix
6473 .  is - index set of rows to remove
6474 .  diag - value put in all diagonals of eliminated rows
6475 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6476 -  b - optional vector of right hand side, that will be adjusted by provided solution
6477 
6478    Level: intermediate
6479 
6480    Notes:
6481    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6482    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6483 
6484    See `MatZeroRows()` for details on how this routine operates.
6485 
6486 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6487           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6488 @*/
6489 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6490 {
6491   PetscInt        numRows;
6492   const PetscInt *rows;
6493 
6494   PetscFunctionBegin;
6495   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6496   PetscValidType(mat, 1);
6497   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6498   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6499   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6500   MatCheckPreallocated(mat, 1);
6501 
6502   PetscCall(ISGetLocalSize(is, &numRows));
6503   PetscCall(ISGetIndices(is, &rows));
6504   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6505   PetscCall(ISRestoreIndices(is, &rows));
6506   PetscFunctionReturn(PETSC_SUCCESS);
6507 }
6508 
6509 /*@
6510    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6511    of a set of rows and columns of a matrix; using local numbering of rows.
6512 
6513    Collective
6514 
6515    Input Parameters:
6516 +  mat - the matrix
6517 .  numRows - the number of rows to remove
6518 .  rows - the global row indices
6519 .  diag - value put in all diagonals of eliminated rows
6520 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6521 -  b - optional vector of right hand side, that will be adjusted by provided solution
6522 
6523    Level: intermediate
6524 
6525    Notes:
6526    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6527    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6528 
6529    See `MatZeroRowsColumns()` for details on how this routine operates.
6530 
6531 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6532           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6533 @*/
6534 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6535 {
6536   IS              is, newis;
6537   const PetscInt *newRows;
6538 
6539   PetscFunctionBegin;
6540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6541   PetscValidType(mat, 1);
6542   if (numRows) PetscValidIntPointer(rows, 3);
6543   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6544   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6545   MatCheckPreallocated(mat, 1);
6546 
6547   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6548   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6549   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6550   PetscCall(ISGetIndices(newis, &newRows));
6551   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6552   PetscCall(ISRestoreIndices(newis, &newRows));
6553   PetscCall(ISDestroy(&newis));
6554   PetscCall(ISDestroy(&is));
6555   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6556   PetscFunctionReturn(PETSC_SUCCESS);
6557 }
6558 
6559 /*@
6560    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6561    of a set of rows and columns of a matrix; using local numbering of rows.
6562 
6563    Collective
6564 
6565    Input Parameters:
6566 +  mat - the matrix
6567 .  is - index set of rows to remove
6568 .  diag - value put in all diagonals of eliminated rows
6569 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6570 -  b - optional vector of right hand side, that will be adjusted by provided solution
6571 
6572    Level: intermediate
6573 
6574    Notes:
6575    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6576    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6577 
6578    See `MatZeroRowsColumns()` for details on how this routine operates.
6579 
6580 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6581           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6582 @*/
6583 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6584 {
6585   PetscInt        numRows;
6586   const PetscInt *rows;
6587 
6588   PetscFunctionBegin;
6589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6590   PetscValidType(mat, 1);
6591   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6593   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6594   MatCheckPreallocated(mat, 1);
6595 
6596   PetscCall(ISGetLocalSize(is, &numRows));
6597   PetscCall(ISGetIndices(is, &rows));
6598   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6599   PetscCall(ISRestoreIndices(is, &rows));
6600   PetscFunctionReturn(PETSC_SUCCESS);
6601 }
6602 
6603 /*@C
6604    MatGetSize - Returns the numbers of rows and columns in a matrix.
6605 
6606    Not Collective
6607 
6608    Input Parameter:
6609 .  mat - the matrix
6610 
6611    Output Parameters:
6612 +  m - the number of global rows
6613 -  n - the number of global columns
6614 
6615    Level: beginner
6616 
6617    Note:
6618    Both output parameters can be `NULL` on input.
6619 
6620 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6621 @*/
6622 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6623 {
6624   PetscFunctionBegin;
6625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6626   if (m) *m = mat->rmap->N;
6627   if (n) *n = mat->cmap->N;
6628   PetscFunctionReturn(PETSC_SUCCESS);
6629 }
6630 
6631 /*@C
6632    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6633    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6634 
6635    Not Collective
6636 
6637    Input Parameter:
6638 .  mat - the matrix
6639 
6640    Output Parameters:
6641 +  m - the number of local rows, use `NULL` to not obtain this value
6642 -  n - the number of local columns, use `NULL` to not obtain this value
6643 
6644    Level: beginner
6645 
6646 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6647 @*/
6648 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6649 {
6650   PetscFunctionBegin;
6651   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6652   if (m) PetscValidIntPointer(m, 2);
6653   if (n) PetscValidIntPointer(n, 3);
6654   if (m) *m = mat->rmap->n;
6655   if (n) *n = mat->cmap->n;
6656   PetscFunctionReturn(PETSC_SUCCESS);
6657 }
6658 
6659 /*@C
6660    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6661    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6662 
6663    Not Collective, unless matrix has not been allocated, then collective
6664 
6665    Input Parameter:
6666 .  mat - the matrix
6667 
6668    Output Parameters:
6669 +  m - the global index of the first local column, use `NULL` to not obtain this value
6670 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6671 
6672    Level: developer
6673 
6674 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6675 @*/
6676 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6677 {
6678   PetscFunctionBegin;
6679   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6680   PetscValidType(mat, 1);
6681   if (m) PetscValidIntPointer(m, 2);
6682   if (n) PetscValidIntPointer(n, 3);
6683   MatCheckPreallocated(mat, 1);
6684   if (m) *m = mat->cmap->rstart;
6685   if (n) *n = mat->cmap->rend;
6686   PetscFunctionReturn(PETSC_SUCCESS);
6687 }
6688 
6689 /*@C
6690    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6691    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
6692    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6693 
6694    Not Collective
6695 
6696    Input Parameter:
6697 .  mat - the matrix
6698 
6699    Output Parameters:
6700 +  m - the global index of the first local row, use `NULL` to not obtain this value
6701 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6702 
6703    Level: beginner
6704 
6705    Note:
6706   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6707   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6708   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6709 
6710 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6711           `PetscLayout`
6712 @*/
6713 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6714 {
6715   PetscFunctionBegin;
6716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6717   PetscValidType(mat, 1);
6718   if (m) PetscValidIntPointer(m, 2);
6719   if (n) PetscValidIntPointer(n, 3);
6720   MatCheckPreallocated(mat, 1);
6721   if (m) *m = mat->rmap->rstart;
6722   if (n) *n = mat->rmap->rend;
6723   PetscFunctionReturn(PETSC_SUCCESS);
6724 }
6725 
6726 /*@C
6727    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6728    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
6729    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6730 
6731    Not Collective, unless matrix has not been allocated
6732 
6733    Input Parameter:
6734 .  mat - the matrix
6735 
6736    Output Parameter:
6737 .  ranges - start of each processors portion plus one more than the total length at the end
6738 
6739    Level: beginner
6740 
6741 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6742 @*/
6743 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6744 {
6745   PetscFunctionBegin;
6746   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6747   PetscValidType(mat, 1);
6748   MatCheckPreallocated(mat, 1);
6749   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6750   PetscFunctionReturn(PETSC_SUCCESS);
6751 }
6752 
6753 /*@C
6754    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6755    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6756 
6757    Not Collective, unless matrix has not been allocated
6758 
6759    Input Parameter:
6760 .  mat - the matrix
6761 
6762    Output Parameter:
6763 .  ranges - start of each processors portion plus one more then the total length at the end
6764 
6765    Level: beginner
6766 
6767 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6768 @*/
6769 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6770 {
6771   PetscFunctionBegin;
6772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6773   PetscValidType(mat, 1);
6774   MatCheckPreallocated(mat, 1);
6775   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6776   PetscFunctionReturn(PETSC_SUCCESS);
6777 }
6778 
6779 /*@C
6780    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6781    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6782    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6783 
6784    Not Collective
6785 
6786    Input Parameter:
6787 .  A - matrix
6788 
6789    Output Parameters:
6790 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6791 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6792 
6793    Level: intermediate
6794 
6795 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6796 @*/
6797 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6798 {
6799   PetscErrorCode (*f)(Mat, IS *, IS *);
6800 
6801   PetscFunctionBegin;
6802   MatCheckPreallocated(A, 1);
6803   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6804   if (f) {
6805     PetscCall((*f)(A, rows, cols));
6806   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6807     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6808     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6809   }
6810   PetscFunctionReturn(PETSC_SUCCESS);
6811 }
6812 
6813 /*@C
6814    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6815    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6816    to complete the factorization.
6817 
6818    Collective
6819 
6820    Input Parameters:
6821 +  fact - the factorized matrix obtained with `MatGetFactor()`
6822 .  mat - the matrix
6823 .  row - row permutation
6824 .  col - column permutation
6825 -  info - structure containing
6826 .vb
6827       levels - number of levels of fill.
6828       expected fill - as ratio of original fill.
6829       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6830                 missing diagonal entries)
6831 .ve
6832 
6833    Level: developer
6834 
6835    Notes:
6836    See [Matrix Factorization](sec_matfactor) for additional information.
6837 
6838    Most users should employ the `KSP` interface for linear solvers
6839    instead of working directly with matrix algebra routines such as this.
6840    See, e.g., `KSPCreate()`.
6841 
6842    Uses the definition of level of fill as in Y. Saad, 2003
6843 
6844    Developer Note:
6845    The Fortran interface is not autogenerated as the
6846    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6847 
6848    References:
6849 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6850 
6851 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6852           `MatGetOrdering()`, `MatFactorInfo`
6853 @*/
6854 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6855 {
6856   PetscFunctionBegin;
6857   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6858   PetscValidType(mat, 2);
6859   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6860   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6861   PetscValidPointer(info, 5);
6862   PetscValidPointer(fact, 1);
6863   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6864   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6865   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6866   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6867   MatCheckPreallocated(mat, 2);
6868 
6869   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6870   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6871   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6872   PetscFunctionReturn(PETSC_SUCCESS);
6873 }
6874 
6875 /*@C
6876    MatICCFactorSymbolic - Performs symbolic incomplete
6877    Cholesky factorization for a symmetric matrix.  Use
6878    `MatCholeskyFactorNumeric()` to complete the factorization.
6879 
6880    Collective
6881 
6882    Input Parameters:
6883 +  fact - the factorized matrix obtained with `MatGetFactor()`
6884 .  mat - the matrix to be factored
6885 .  perm - row and column permutation
6886 -  info - structure containing
6887 .vb
6888       levels - number of levels of fill.
6889       expected fill - as ratio of original fill.
6890 .ve
6891 
6892    Level: developer
6893 
6894    Notes:
6895    Most users should employ the `KSP` interface for linear solvers
6896    instead of working directly with matrix algebra routines such as this.
6897    See, e.g., `KSPCreate()`.
6898 
6899    This uses the definition of level of fill as in Y. Saad, 2003
6900 
6901    Developer Note:
6902    The Fortran interface is not autogenerated as the
6903    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6904 
6905    References:
6906 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6907 
6908 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6909 @*/
6910 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6911 {
6912   PetscFunctionBegin;
6913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6914   PetscValidType(mat, 2);
6915   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6916   PetscValidPointer(info, 4);
6917   PetscValidPointer(fact, 1);
6918   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6919   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6920   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6921   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6922   MatCheckPreallocated(mat, 2);
6923 
6924   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6925   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6926   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6927   PetscFunctionReturn(PETSC_SUCCESS);
6928 }
6929 
6930 /*@C
6931    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6932    points to an array of valid matrices, they may be reused to store the new
6933    submatrices.
6934 
6935    Collective
6936 
6937    Input Parameters:
6938 +  mat - the matrix
6939 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6940 .  irow - index set of rows to extract
6941 .  icol - index set of columns to extract
6942 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6943 
6944    Output Parameter:
6945 .  submat - the array of submatrices
6946 
6947    Level: advanced
6948 
6949    Notes:
6950    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6951    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6952    to extract a parallel submatrix.
6953 
6954    Some matrix types place restrictions on the row and column
6955    indices, such as that they be sorted or that they be equal to each other.
6956 
6957    The index sets may not have duplicate entries.
6958 
6959    When extracting submatrices from a parallel matrix, each processor can
6960    form a different submatrix by setting the rows and columns of its
6961    individual index sets according to the local submatrix desired.
6962 
6963    When finished using the submatrices, the user should destroy
6964    them with `MatDestroySubMatrices()`.
6965 
6966    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6967    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6968 
6969    This routine creates the matrices in submat; you should NOT create them before
6970    calling it. It also allocates the array of matrix pointers submat.
6971 
6972    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6973    request one row/column in a block, they must request all rows/columns that are in
6974    that block. For example, if the block size is 2 you cannot request just row 0 and
6975    column 0.
6976 
6977    Fortran Note:
6978    The Fortran interface is slightly different from that given below; it
6979    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6980 
6981 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6982 @*/
6983 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6984 {
6985   PetscInt  i;
6986   PetscBool eq;
6987 
6988   PetscFunctionBegin;
6989   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6990   PetscValidType(mat, 1);
6991   if (n) {
6992     PetscValidPointer(irow, 3);
6993     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6994     PetscValidPointer(icol, 4);
6995     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6996   }
6997   PetscValidPointer(submat, 6);
6998   if (n && scall == MAT_REUSE_MATRIX) {
6999     PetscValidPointer(*submat, 6);
7000     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7001   }
7002   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7003   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7004   MatCheckPreallocated(mat, 1);
7005   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7006   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7007   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7008   for (i = 0; i < n; i++) {
7009     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7010     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7011     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7012 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7013     if (mat->boundtocpu && mat->bindingpropagates) {
7014       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7015       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7016     }
7017 #endif
7018   }
7019   PetscFunctionReturn(PETSC_SUCCESS);
7020 }
7021 
7022 /*@C
7023    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7024 
7025    Collective
7026 
7027    Input Parameters:
7028 +  mat - the matrix
7029 .  n   - the number of submatrixes to be extracted
7030 .  irow - index set of rows to extract
7031 .  icol - index set of columns to extract
7032 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7033 
7034    Output Parameter:
7035 .  submat - the array of submatrices
7036 
7037    Level: advanced
7038 
7039    Note:
7040    This is used by `PCGASM`
7041 
7042 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7043 @*/
7044 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7045 {
7046   PetscInt  i;
7047   PetscBool eq;
7048 
7049   PetscFunctionBegin;
7050   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7051   PetscValidType(mat, 1);
7052   if (n) {
7053     PetscValidPointer(irow, 3);
7054     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7055     PetscValidPointer(icol, 4);
7056     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7057   }
7058   PetscValidPointer(submat, 6);
7059   if (n && scall == MAT_REUSE_MATRIX) {
7060     PetscValidPointer(*submat, 6);
7061     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7062   }
7063   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7064   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7065   MatCheckPreallocated(mat, 1);
7066 
7067   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7068   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7069   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7070   for (i = 0; i < n; i++) {
7071     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7072     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7073   }
7074   PetscFunctionReturn(PETSC_SUCCESS);
7075 }
7076 
7077 /*@C
7078    MatDestroyMatrices - Destroys an array of matrices.
7079 
7080    Collective
7081 
7082    Input Parameters:
7083 +  n - the number of local matrices
7084 -  mat - the matrices (this is a pointer to the array of matrices)
7085 
7086    Level: advanced
7087 
7088     Note:
7089     Frees not only the matrices, but also the array that contains the matrices
7090 
7091     Fortran Note:
7092     This does not free the array.
7093 
7094 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7095 @*/
7096 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7097 {
7098   PetscInt i;
7099 
7100   PetscFunctionBegin;
7101   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7102   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7103   PetscValidPointer(mat, 2);
7104 
7105   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7106 
7107   /* memory is allocated even if n = 0 */
7108   PetscCall(PetscFree(*mat));
7109   PetscFunctionReturn(PETSC_SUCCESS);
7110 }
7111 
7112 /*@C
7113    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7114 
7115    Collective
7116 
7117    Input Parameters:
7118 +  n - the number of local matrices
7119 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7120                        sequence of `MatCreateSubMatrices()`)
7121 
7122    Level: advanced
7123 
7124     Note:
7125     Frees not only the matrices, but also the array that contains the matrices
7126 
7127     Fortran Note:
7128     This does not free the array.
7129 
7130 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7131 @*/
7132 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7133 {
7134   Mat mat0;
7135 
7136   PetscFunctionBegin;
7137   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7138   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7139   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7140   PetscValidPointer(mat, 2);
7141 
7142   mat0 = (*mat)[0];
7143   if (mat0 && mat0->ops->destroysubmatrices) {
7144     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7145   } else {
7146     PetscCall(MatDestroyMatrices(n, mat));
7147   }
7148   PetscFunctionReturn(PETSC_SUCCESS);
7149 }
7150 
7151 /*@C
7152    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7153 
7154    Collective
7155 
7156    Input Parameter:
7157 .  mat - the matrix
7158 
7159    Output Parameter:
7160 .  matstruct - the sequential matrix with the nonzero structure of mat
7161 
7162   Level: developer
7163 
7164 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7165 @*/
7166 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7167 {
7168   PetscFunctionBegin;
7169   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7170   PetscValidPointer(matstruct, 2);
7171 
7172   PetscValidType(mat, 1);
7173   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7174   MatCheckPreallocated(mat, 1);
7175 
7176   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7177   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7178   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7179   PetscFunctionReturn(PETSC_SUCCESS);
7180 }
7181 
7182 /*@C
7183    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7184 
7185    Collective
7186 
7187    Input Parameter:
7188 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7189                        sequence of `MatGetSequentialNonzeroStructure()`)
7190 
7191    Level: advanced
7192 
7193     Note:
7194     Frees not only the matrices, but also the array that contains the matrices
7195 
7196 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7197 @*/
7198 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7199 {
7200   PetscFunctionBegin;
7201   PetscValidPointer(mat, 1);
7202   PetscCall(MatDestroy(mat));
7203   PetscFunctionReturn(PETSC_SUCCESS);
7204 }
7205 
7206 /*@
7207    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7208    replaces the index sets by larger ones that represent submatrices with
7209    additional overlap.
7210 
7211    Collective
7212 
7213    Input Parameters:
7214 +  mat - the matrix
7215 .  n   - the number of index sets
7216 .  is  - the array of index sets (these index sets will changed during the call)
7217 -  ov  - the additional overlap requested
7218 
7219    Options Database Key:
7220 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7221 
7222    Level: developer
7223 
7224    Note:
7225    The computed overlap preserves the matrix block sizes when the blocks are square.
7226    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7227    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7228 
7229 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7230 @*/
7231 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7232 {
7233   PetscInt i, bs, cbs;
7234 
7235   PetscFunctionBegin;
7236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7237   PetscValidType(mat, 1);
7238   PetscValidLogicalCollectiveInt(mat, n, 2);
7239   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7240   if (n) {
7241     PetscValidPointer(is, 3);
7242     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7243   }
7244   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7245   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7246   MatCheckPreallocated(mat, 1);
7247 
7248   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7249   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7250   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7251   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7252   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7253   if (bs == cbs) {
7254     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7255   }
7256   PetscFunctionReturn(PETSC_SUCCESS);
7257 }
7258 
7259 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7260 
7261 /*@
7262    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7263    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7264    additional overlap.
7265 
7266    Collective
7267 
7268    Input Parameters:
7269 +  mat - the matrix
7270 .  n   - the number of index sets
7271 .  is  - the array of index sets (these index sets will changed during the call)
7272 -  ov  - the additional overlap requested
7273 
7274 `   Options Database Key:
7275 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7276 
7277    Level: developer
7278 
7279 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7280 @*/
7281 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7282 {
7283   PetscInt i;
7284 
7285   PetscFunctionBegin;
7286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7287   PetscValidType(mat, 1);
7288   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7289   if (n) {
7290     PetscValidPointer(is, 3);
7291     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7292   }
7293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7295   MatCheckPreallocated(mat, 1);
7296   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7297   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7298   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7299   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7300   PetscFunctionReturn(PETSC_SUCCESS);
7301 }
7302 
7303 /*@
7304    MatGetBlockSize - Returns the matrix block size.
7305 
7306    Not Collective
7307 
7308    Input Parameter:
7309 .  mat - the matrix
7310 
7311    Output Parameter:
7312 .  bs - block size
7313 
7314    Level: intermediate
7315 
7316    Notes:
7317     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7318 
7319    If the block size has not been set yet this routine returns 1.
7320 
7321 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7322 @*/
7323 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7324 {
7325   PetscFunctionBegin;
7326   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7327   PetscValidIntPointer(bs, 2);
7328   *bs = PetscAbs(mat->rmap->bs);
7329   PetscFunctionReturn(PETSC_SUCCESS);
7330 }
7331 
7332 /*@
7333    MatGetBlockSizes - Returns the matrix block row and column sizes.
7334 
7335    Not Collective
7336 
7337    Input Parameter:
7338 .  mat - the matrix
7339 
7340    Output Parameters:
7341 +  rbs - row block size
7342 -  cbs - column block size
7343 
7344    Level: intermediate
7345 
7346    Notes:
7347     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7348     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7349 
7350    If a block size has not been set yet this routine returns 1.
7351 
7352 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7353 @*/
7354 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7355 {
7356   PetscFunctionBegin;
7357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7358   if (rbs) PetscValidIntPointer(rbs, 2);
7359   if (cbs) PetscValidIntPointer(cbs, 3);
7360   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7361   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7362   PetscFunctionReturn(PETSC_SUCCESS);
7363 }
7364 
7365 /*@
7366    MatSetBlockSize - Sets the matrix block size.
7367 
7368    Logically Collective
7369 
7370    Input Parameters:
7371 +  mat - the matrix
7372 -  bs - block size
7373 
7374    Level: intermediate
7375 
7376    Notes:
7377     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7378     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7379 
7380     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7381     is compatible with the matrix local sizes.
7382 
7383 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7384 @*/
7385 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7386 {
7387   PetscFunctionBegin;
7388   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7389   PetscValidLogicalCollectiveInt(mat, bs, 2);
7390   PetscCall(MatSetBlockSizes(mat, bs, bs));
7391   PetscFunctionReturn(PETSC_SUCCESS);
7392 }
7393 
7394 typedef struct {
7395   PetscInt         n;
7396   IS              *is;
7397   Mat             *mat;
7398   PetscObjectState nonzerostate;
7399   Mat              C;
7400 } EnvelopeData;
7401 
7402 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7403 {
7404   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7405   PetscCall(PetscFree(edata->is));
7406   PetscCall(PetscFree(edata));
7407   return PETSC_SUCCESS;
7408 }
7409 
7410 /*
7411    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7412          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7413 
7414    Collective
7415 
7416    Input Parameter:
7417 .  mat - the matrix
7418 
7419    Notes:
7420      There can be zeros within the blocks
7421 
7422      The blocks can overlap between processes, including laying on more than two processes
7423 
7424 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7425 */
7426 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7427 {
7428   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7429   PetscInt          *diag, *odiag, sc;
7430   VecScatter         scatter;
7431   PetscScalar       *seqv;
7432   const PetscScalar *parv;
7433   const PetscInt    *ia, *ja;
7434   PetscBool          set, flag, done;
7435   Mat                AA = mat, A;
7436   MPI_Comm           comm;
7437   PetscMPIInt        rank, size, tag;
7438   MPI_Status         status;
7439   PetscContainer     container;
7440   EnvelopeData      *edata;
7441   Vec                seq, par;
7442   IS                 isglobal;
7443 
7444   PetscFunctionBegin;
7445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7446   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7447   if (!set || !flag) {
7448     /* TOO: only needs nonzero structure of transpose */
7449     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7450     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7451   }
7452   PetscCall(MatAIJGetLocalMat(AA, &A));
7453   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7454   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7455 
7456   PetscCall(MatGetLocalSize(mat, &n, NULL));
7457   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7458   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7459   PetscCallMPI(MPI_Comm_size(comm, &size));
7460   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7461 
7462   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7463 
7464   if (rank > 0) {
7465     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7466     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7467   }
7468   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7469   for (i = 0; i < n; i++) {
7470     env = PetscMax(env, ja[ia[i + 1] - 1]);
7471     II  = rstart + i;
7472     if (env == II) {
7473       starts[lblocks]  = tbs;
7474       sizes[lblocks++] = 1 + II - tbs;
7475       tbs              = 1 + II;
7476     }
7477   }
7478   if (rank < size - 1) {
7479     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7480     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7481   }
7482 
7483   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7484   if (!set || !flag) PetscCall(MatDestroy(&AA));
7485   PetscCall(MatDestroy(&A));
7486 
7487   PetscCall(PetscNew(&edata));
7488   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7489   edata->n = lblocks;
7490   /* create IS needed for extracting blocks from the original matrix */
7491   PetscCall(PetscMalloc1(lblocks, &edata->is));
7492   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7493 
7494   /* Create the resulting inverse matrix structure with preallocation information */
7495   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7496   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7497   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7498   PetscCall(MatSetType(edata->C, MATAIJ));
7499 
7500   /* Communicate the start and end of each row, from each block to the correct rank */
7501   /* TODO: Use PetscSF instead of VecScatter */
7502   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7503   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7504   PetscCall(VecGetArrayWrite(seq, &seqv));
7505   for (PetscInt i = 0; i < lblocks; i++) {
7506     for (PetscInt j = 0; j < sizes[i]; j++) {
7507       seqv[cnt]     = starts[i];
7508       seqv[cnt + 1] = starts[i] + sizes[i];
7509       cnt += 2;
7510     }
7511   }
7512   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7513   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7514   sc -= cnt;
7515   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7516   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7517   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7518   PetscCall(ISDestroy(&isglobal));
7519   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7520   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7521   PetscCall(VecScatterDestroy(&scatter));
7522   PetscCall(VecDestroy(&seq));
7523   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7524   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7525   PetscCall(VecGetArrayRead(par, &parv));
7526   cnt = 0;
7527   PetscCall(MatGetSize(mat, NULL, &n));
7528   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7529     PetscInt start, end, d = 0, od = 0;
7530 
7531     start = (PetscInt)PetscRealPart(parv[cnt]);
7532     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7533     cnt += 2;
7534 
7535     if (start < cstart) {
7536       od += cstart - start + n - cend;
7537       d += cend - cstart;
7538     } else if (start < cend) {
7539       od += n - cend;
7540       d += cend - start;
7541     } else od += n - start;
7542     if (end <= cstart) {
7543       od -= cstart - end + n - cend;
7544       d -= cend - cstart;
7545     } else if (end < cend) {
7546       od -= n - cend;
7547       d -= cend - end;
7548     } else od -= n - end;
7549 
7550     odiag[i] = od;
7551     diag[i]  = d;
7552   }
7553   PetscCall(VecRestoreArrayRead(par, &parv));
7554   PetscCall(VecDestroy(&par));
7555   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7556   PetscCall(PetscFree2(diag, odiag));
7557   PetscCall(PetscFree2(sizes, starts));
7558 
7559   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7560   PetscCall(PetscContainerSetPointer(container, edata));
7561   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7562   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7563   PetscCall(PetscObjectDereference((PetscObject)container));
7564   PetscFunctionReturn(PETSC_SUCCESS);
7565 }
7566 
7567 /*@
7568   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7569 
7570   Collective
7571 
7572   Input Parameters:
7573 + A - the matrix
7574 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7575 
7576   Output Parameter:
7577 . C - matrix with inverted block diagonal of `A`
7578 
7579   Level: advanced
7580 
7581   Note:
7582      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7583 
7584 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7585 @*/
7586 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7587 {
7588   PetscContainer   container;
7589   EnvelopeData    *edata;
7590   PetscObjectState nonzerostate;
7591 
7592   PetscFunctionBegin;
7593   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7594   if (!container) {
7595     PetscCall(MatComputeVariableBlockEnvelope(A));
7596     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7597   }
7598   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7599   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7600   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7601   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7602 
7603   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7604   *C = edata->C;
7605 
7606   for (PetscInt i = 0; i < edata->n; i++) {
7607     Mat          D;
7608     PetscScalar *dvalues;
7609 
7610     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7611     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7612     PetscCall(MatSeqDenseInvert(D));
7613     PetscCall(MatDenseGetArray(D, &dvalues));
7614     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7615     PetscCall(MatDestroy(&D));
7616   }
7617   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7618   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7619   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7620   PetscFunctionReturn(PETSC_SUCCESS);
7621 }
7622 
7623 /*@
7624    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7625 
7626    Logically Collective
7627 
7628    Input Parameters:
7629 +  mat - the matrix
7630 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7631 -  bsizes - the block sizes
7632 
7633    Level: intermediate
7634 
7635    Notes:
7636     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7637 
7638     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.
7639 
7640 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7641           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7642 @*/
7643 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7644 {
7645   PetscInt i, ncnt = 0, nlocal;
7646 
7647   PetscFunctionBegin;
7648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7649   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7650   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7651   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7652   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);
7653   PetscCall(PetscFree(mat->bsizes));
7654   mat->nblocks = nblocks;
7655   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7656   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7657   PetscFunctionReturn(PETSC_SUCCESS);
7658 }
7659 
7660 /*@C
7661    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7662 
7663    Logically Collective; No Fortran Support
7664 
7665    Input Parameter:
7666 .  mat - the matrix
7667 
7668    Output Parameters:
7669 +  nblocks - the number of blocks on this process
7670 -  bsizes - the block sizes
7671 
7672    Level: intermediate
7673 
7674 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7675 @*/
7676 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7677 {
7678   PetscFunctionBegin;
7679   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7680   *nblocks = mat->nblocks;
7681   *bsizes  = mat->bsizes;
7682   PetscFunctionReturn(PETSC_SUCCESS);
7683 }
7684 
7685 /*@
7686    MatSetBlockSizes - Sets the matrix block row and column sizes.
7687 
7688    Logically Collective
7689 
7690    Input Parameters:
7691 +  mat - the matrix
7692 .  rbs - row block size
7693 -  cbs - column block size
7694 
7695    Level: intermediate
7696 
7697    Notes:
7698     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7699     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7700     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7701 
7702     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7703     are compatible with the matrix local sizes.
7704 
7705     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7706 
7707 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7708 @*/
7709 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7710 {
7711   PetscFunctionBegin;
7712   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7713   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7714   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7715   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7716   if (mat->rmap->refcnt) {
7717     ISLocalToGlobalMapping l2g  = NULL;
7718     PetscLayout            nmap = NULL;
7719 
7720     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7721     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7722     PetscCall(PetscLayoutDestroy(&mat->rmap));
7723     mat->rmap          = nmap;
7724     mat->rmap->mapping = l2g;
7725   }
7726   if (mat->cmap->refcnt) {
7727     ISLocalToGlobalMapping l2g  = NULL;
7728     PetscLayout            nmap = NULL;
7729 
7730     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7731     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7732     PetscCall(PetscLayoutDestroy(&mat->cmap));
7733     mat->cmap          = nmap;
7734     mat->cmap->mapping = l2g;
7735   }
7736   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7737   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7738   PetscFunctionReturn(PETSC_SUCCESS);
7739 }
7740 
7741 /*@
7742    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7743 
7744    Logically Collective
7745 
7746    Input Parameters:
7747 +  mat - the matrix
7748 .  fromRow - matrix from which to copy row block size
7749 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7750 
7751    Level: developer
7752 
7753 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7754 @*/
7755 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7756 {
7757   PetscFunctionBegin;
7758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7759   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7760   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7761   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7762   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7763   PetscFunctionReturn(PETSC_SUCCESS);
7764 }
7765 
7766 /*@
7767    MatResidual - Default routine to calculate the residual r = b - Ax
7768 
7769    Collective
7770 
7771    Input Parameters:
7772 +  mat - the matrix
7773 .  b   - the right-hand-side
7774 -  x   - the approximate solution
7775 
7776    Output Parameter:
7777 .  r - location to store the residual
7778 
7779    Level: developer
7780 
7781 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7782 @*/
7783 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7784 {
7785   PetscFunctionBegin;
7786   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7787   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7788   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7789   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7790   PetscValidType(mat, 1);
7791   MatCheckPreallocated(mat, 1);
7792   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7793   if (!mat->ops->residual) {
7794     PetscCall(MatMult(mat, x, r));
7795     PetscCall(VecAYPX(r, -1.0, b));
7796   } else {
7797     PetscUseTypeMethod(mat, residual, b, x, r);
7798   }
7799   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7800   PetscFunctionReturn(PETSC_SUCCESS);
7801 }
7802 
7803 /*MC
7804     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7805 
7806     Synopsis:
7807     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7808 
7809     Not Collective
7810 
7811     Input Parameters:
7812 +   A - the matrix
7813 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7814 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7815 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7816                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7817                  always used.
7818 
7819     Output Parameters:
7820 +   n - number of local rows in the (possibly compressed) matrix
7821 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7822 .   ja - the column indices
7823 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7824            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7825 
7826     Level: developer
7827 
7828     Note:
7829     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7830 
7831 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7832 M*/
7833 
7834 /*MC
7835     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7836 
7837     Synopsis:
7838     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7839 
7840     Not Collective
7841 
7842     Input Parameters:
7843 +   A - the  matrix
7844 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7845 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7846     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7847                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7848                  always used.
7849 .   n - number of local rows in the (possibly compressed) matrix
7850 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7851 .   ja - the column indices
7852 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7853            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7854 
7855     Level: developer
7856 
7857 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7858 M*/
7859 
7860 /*@C
7861     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7862 
7863    Collective
7864 
7865     Input Parameters:
7866 +   mat - the matrix
7867 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7868 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7869 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7870                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7871                  always used.
7872 
7873     Output Parameters:
7874 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7875 .   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
7876 .   ja - the column indices, use `NULL` if not needed
7877 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7878            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7879 
7880     Level: developer
7881 
7882     Notes:
7883     You CANNOT change any of the ia[] or ja[] values.
7884 
7885     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7886 
7887     Fortran Notes:
7888     Use
7889 .vb
7890     PetscInt, pointer :: ia(:),ja(:)
7891     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7892     ! Access the ith and jth entries via ia(i) and ja(j)
7893 .ve
7894    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7895 
7896 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7897 @*/
7898 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7899 {
7900   PetscFunctionBegin;
7901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7902   PetscValidType(mat, 1);
7903   if (n) PetscValidIntPointer(n, 5);
7904   if (ia) PetscValidPointer(ia, 6);
7905   if (ja) PetscValidPointer(ja, 7);
7906   if (done) PetscValidBoolPointer(done, 8);
7907   MatCheckPreallocated(mat, 1);
7908   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7909   else {
7910     if (done) *done = PETSC_TRUE;
7911     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7912     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7913     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7914   }
7915   PetscFunctionReturn(PETSC_SUCCESS);
7916 }
7917 
7918 /*@C
7919     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7920 
7921     Collective
7922 
7923     Input Parameters:
7924 +   mat - the matrix
7925 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7926 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7927                 symmetrized
7928 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7929                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7930                  always used.
7931 .   n - number of columns in the (possibly compressed) matrix
7932 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7933 -   ja - the row indices
7934 
7935     Output Parameter:
7936 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7937 
7938     Level: developer
7939 
7940 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7941 @*/
7942 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7943 {
7944   PetscFunctionBegin;
7945   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7946   PetscValidType(mat, 1);
7947   PetscValidIntPointer(n, 5);
7948   if (ia) PetscValidPointer(ia, 6);
7949   if (ja) PetscValidPointer(ja, 7);
7950   PetscValidBoolPointer(done, 8);
7951   MatCheckPreallocated(mat, 1);
7952   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7953   else {
7954     *done = PETSC_TRUE;
7955     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7956   }
7957   PetscFunctionReturn(PETSC_SUCCESS);
7958 }
7959 
7960 /*@C
7961     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7962 
7963     Collective
7964 
7965     Input Parameters:
7966 +   mat - the matrix
7967 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7968 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7969 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7970                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7971                  always used.
7972 .   n - size of (possibly compressed) matrix
7973 .   ia - the row pointers
7974 -   ja - the column indices
7975 
7976     Output Parameter:
7977 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7978 
7979     Level: developer
7980 
7981     Note:
7982     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7983     us of the array after it has been restored. If you pass `NULL`, it will
7984     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7985 
7986     Fortran Note:
7987    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7988 
7989 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7990 @*/
7991 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7992 {
7993   PetscFunctionBegin;
7994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7995   PetscValidType(mat, 1);
7996   if (ia) PetscValidPointer(ia, 6);
7997   if (ja) PetscValidPointer(ja, 7);
7998   if (done) PetscValidBoolPointer(done, 8);
7999   MatCheckPreallocated(mat, 1);
8000 
8001   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8002   else {
8003     if (done) *done = PETSC_TRUE;
8004     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8005     if (n) *n = 0;
8006     if (ia) *ia = NULL;
8007     if (ja) *ja = NULL;
8008   }
8009   PetscFunctionReturn(PETSC_SUCCESS);
8010 }
8011 
8012 /*@C
8013     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8014 
8015     Collective
8016 
8017     Input Parameters:
8018 +   mat - the matrix
8019 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8020 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8021 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8022                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8023                  always used.
8024 
8025     Output Parameters:
8026 +   n - size of (possibly compressed) matrix
8027 .   ia - the column pointers
8028 .   ja - the row indices
8029 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8030 
8031     Level: developer
8032 
8033 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8034 @*/
8035 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8036 {
8037   PetscFunctionBegin;
8038   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8039   PetscValidType(mat, 1);
8040   if (ia) PetscValidPointer(ia, 6);
8041   if (ja) PetscValidPointer(ja, 7);
8042   PetscValidBoolPointer(done, 8);
8043   MatCheckPreallocated(mat, 1);
8044 
8045   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8046   else {
8047     *done = PETSC_TRUE;
8048     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8049     if (n) *n = 0;
8050     if (ia) *ia = NULL;
8051     if (ja) *ja = NULL;
8052   }
8053   PetscFunctionReturn(PETSC_SUCCESS);
8054 }
8055 
8056 /*@C
8057     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8058 
8059     Collective
8060 
8061     Input Parameters:
8062 +   mat - the matrix
8063 .   ncolors - maximum color value
8064 .   n   - number of entries in colorarray
8065 -   colorarray - array indicating color for each column
8066 
8067     Output Parameter:
8068 .   iscoloring - coloring generated using colorarray information
8069 
8070     Level: developer
8071 
8072 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8073 @*/
8074 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8075 {
8076   PetscFunctionBegin;
8077   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8078   PetscValidType(mat, 1);
8079   PetscValidIntPointer(colorarray, 4);
8080   PetscValidPointer(iscoloring, 5);
8081   MatCheckPreallocated(mat, 1);
8082 
8083   if (!mat->ops->coloringpatch) {
8084     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8085   } else {
8086     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8087   }
8088   PetscFunctionReturn(PETSC_SUCCESS);
8089 }
8090 
8091 /*@
8092    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8093 
8094    Logically Collective
8095 
8096    Input Parameter:
8097 .  mat - the factored matrix to be reset
8098 
8099    Level: developer
8100 
8101    Notes:
8102    This routine should be used only with factored matrices formed by in-place
8103    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8104    format).  This option can save memory, for example, when solving nonlinear
8105    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8106    ILU(0) preconditioner.
8107 
8108    One can specify in-place ILU(0) factorization by calling
8109 .vb
8110      PCType(pc,PCILU);
8111      PCFactorSeUseInPlace(pc);
8112 .ve
8113    or by using the options -pc_type ilu -pc_factor_in_place
8114 
8115    In-place factorization ILU(0) can also be used as a local
8116    solver for the blocks within the block Jacobi or additive Schwarz
8117    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8118    for details on setting local solver options.
8119 
8120    Most users should employ the `KSP` interface for linear solvers
8121    instead of working directly with matrix algebra routines such as this.
8122    See, e.g., `KSPCreate()`.
8123 
8124 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8125 @*/
8126 PetscErrorCode MatSetUnfactored(Mat mat)
8127 {
8128   PetscFunctionBegin;
8129   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8130   PetscValidType(mat, 1);
8131   MatCheckPreallocated(mat, 1);
8132   mat->factortype = MAT_FACTOR_NONE;
8133   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8134   PetscUseTypeMethod(mat, setunfactored);
8135   PetscFunctionReturn(PETSC_SUCCESS);
8136 }
8137 
8138 /*MC
8139     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8140 
8141     Synopsis:
8142     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8143 
8144     Not Collective
8145 
8146     Input Parameter:
8147 .   x - matrix
8148 
8149     Output Parameters:
8150 +   xx_v - the Fortran pointer to the array
8151 -   ierr - error code
8152 
8153     Example of Usage:
8154 .vb
8155       PetscScalar, pointer xx_v(:,:)
8156       ....
8157       call MatDenseGetArrayF90(x,xx_v,ierr)
8158       a = xx_v(3)
8159       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8160 .ve
8161 
8162     Level: advanced
8163 
8164 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8165 M*/
8166 
8167 /*MC
8168     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8169     accessed with `MatDenseGetArrayF90()`.
8170 
8171     Synopsis:
8172     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8173 
8174     Not Collective
8175 
8176     Input Parameters:
8177 +   x - matrix
8178 -   xx_v - the Fortran90 pointer to the array
8179 
8180     Output Parameter:
8181 .   ierr - error code
8182 
8183     Example of Usage:
8184 .vb
8185        PetscScalar, pointer xx_v(:,:)
8186        ....
8187        call MatDenseGetArrayF90(x,xx_v,ierr)
8188        a = xx_v(3)
8189        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8190 .ve
8191 
8192     Level: advanced
8193 
8194 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8195 M*/
8196 
8197 /*MC
8198     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8199 
8200     Synopsis:
8201     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8202 
8203     Not Collective
8204 
8205     Input Parameter:
8206 .   x - matrix
8207 
8208     Output Parameters:
8209 +   xx_v - the Fortran pointer to the array
8210 -   ierr - error code
8211 
8212     Example of Usage:
8213 .vb
8214       PetscScalar, pointer xx_v(:)
8215       ....
8216       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8217       a = xx_v(3)
8218       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8219 .ve
8220 
8221     Level: advanced
8222 
8223 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8224 M*/
8225 
8226 /*MC
8227     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8228     accessed with `MatSeqAIJGetArrayF90()`.
8229 
8230     Synopsis:
8231     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8232 
8233     Not Collective
8234 
8235     Input Parameters:
8236 +   x - matrix
8237 -   xx_v - the Fortran90 pointer to the array
8238 
8239     Output Parameter:
8240 .   ierr - error code
8241 
8242     Example of Usage:
8243 .vb
8244        PetscScalar, pointer xx_v(:)
8245        ....
8246        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8247        a = xx_v(3)
8248        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8249 .ve
8250 
8251     Level: advanced
8252 
8253 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8254 M*/
8255 
8256 /*@
8257     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8258                       as the original matrix.
8259 
8260     Collective
8261 
8262     Input Parameters:
8263 +   mat - the original matrix
8264 .   isrow - parallel `IS` containing the rows this processor should obtain
8265 .   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.
8266 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8267 
8268     Output Parameter:
8269 .   newmat - the new submatrix, of the same type as the original matrix
8270 
8271     Level: advanced
8272 
8273     Notes:
8274     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8275 
8276     Some matrix types place restrictions on the row and column indices, such
8277     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;
8278     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8279 
8280     The index sets may not have duplicate entries.
8281 
8282       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8283    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8284    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8285    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8286    you are finished using it.
8287 
8288     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8289     the input matrix.
8290 
8291     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8292 
8293    Example usage:
8294    Consider the following 8x8 matrix with 34 non-zero values, that is
8295    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8296    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8297    as follows
8298 .vb
8299             1  2  0  |  0  3  0  |  0  4
8300     Proc0   0  5  6  |  7  0  0  |  8  0
8301             9  0 10  | 11  0  0  | 12  0
8302     -------------------------------------
8303            13  0 14  | 15 16 17  |  0  0
8304     Proc1   0 18  0  | 19 20 21  |  0  0
8305             0  0  0  | 22 23  0  | 24  0
8306     -------------------------------------
8307     Proc2  25 26 27  |  0  0 28  | 29  0
8308            30  0  0  | 31 32 33  |  0 34
8309 .ve
8310 
8311     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8312 
8313 .vb
8314             2  0  |  0  3  0  |  0
8315     Proc0   5  6  |  7  0  0  |  8
8316     -------------------------------
8317     Proc1  18  0  | 19 20 21  |  0
8318     -------------------------------
8319     Proc2  26 27  |  0  0 28  | 29
8320             0  0  | 31 32 33  |  0
8321 .ve
8322 
8323 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8324 @*/
8325 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8326 {
8327   PetscMPIInt size;
8328   Mat        *local;
8329   IS          iscoltmp;
8330   PetscBool   flg;
8331 
8332   PetscFunctionBegin;
8333   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8334   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8335   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8336   PetscValidPointer(newmat, 5);
8337   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8338   PetscValidType(mat, 1);
8339   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8340   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8341 
8342   MatCheckPreallocated(mat, 1);
8343   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8344 
8345   if (!iscol || isrow == iscol) {
8346     PetscBool   stride;
8347     PetscMPIInt grabentirematrix = 0, grab;
8348     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8349     if (stride) {
8350       PetscInt first, step, n, rstart, rend;
8351       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8352       if (step == 1) {
8353         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8354         if (rstart == first) {
8355           PetscCall(ISGetLocalSize(isrow, &n));
8356           if (n == rend - rstart) grabentirematrix = 1;
8357         }
8358       }
8359     }
8360     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8361     if (grab) {
8362       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8363       if (cll == MAT_INITIAL_MATRIX) {
8364         *newmat = mat;
8365         PetscCall(PetscObjectReference((PetscObject)mat));
8366       }
8367       PetscFunctionReturn(PETSC_SUCCESS);
8368     }
8369   }
8370 
8371   if (!iscol) {
8372     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8373   } else {
8374     iscoltmp = iscol;
8375   }
8376 
8377   /* if original matrix is on just one processor then use submatrix generated */
8378   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8379     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8380     goto setproperties;
8381   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8382     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8383     *newmat = *local;
8384     PetscCall(PetscFree(local));
8385     goto setproperties;
8386   } else if (!mat->ops->createsubmatrix) {
8387     /* Create a new matrix type that implements the operation using the full matrix */
8388     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8389     switch (cll) {
8390     case MAT_INITIAL_MATRIX:
8391       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8392       break;
8393     case MAT_REUSE_MATRIX:
8394       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8395       break;
8396     default:
8397       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8398     }
8399     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8400     goto setproperties;
8401   }
8402 
8403   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8404   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8405   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8406 
8407 setproperties:
8408   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8409   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8410   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8411   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8412   PetscFunctionReturn(PETSC_SUCCESS);
8413 }
8414 
8415 /*@
8416    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8417 
8418    Not Collective
8419 
8420    Input Parameters:
8421 +  A - the matrix we wish to propagate options from
8422 -  B - the matrix we wish to propagate options to
8423 
8424    Level: beginner
8425 
8426    Note:
8427    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8428 
8429 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8430 @*/
8431 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8432 {
8433   PetscFunctionBegin;
8434   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8435   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8436   B->symmetry_eternal            = A->symmetry_eternal;
8437   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8438   B->symmetric                   = A->symmetric;
8439   B->structurally_symmetric      = A->structurally_symmetric;
8440   B->spd                         = A->spd;
8441   B->hermitian                   = A->hermitian;
8442   PetscFunctionReturn(PETSC_SUCCESS);
8443 }
8444 
8445 /*@
8446    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8447    used during the assembly process to store values that belong to
8448    other processors.
8449 
8450    Not Collective
8451 
8452    Input Parameters:
8453 +  mat   - the matrix
8454 .  size  - the initial size of the stash.
8455 -  bsize - the initial size of the block-stash(if used).
8456 
8457    Options Database Keys:
8458 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8459 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8460 
8461    Level: intermediate
8462 
8463    Notes:
8464      The block-stash is used for values set with `MatSetValuesBlocked()` while
8465      the stash is used for values set with `MatSetValues()`
8466 
8467      Run with the option -info and look for output of the form
8468      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8469      to determine the appropriate value, MM, to use for size and
8470      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8471      to determine the value, BMM to use for bsize
8472 
8473 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8474 @*/
8475 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8476 {
8477   PetscFunctionBegin;
8478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8479   PetscValidType(mat, 1);
8480   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8481   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8482   PetscFunctionReturn(PETSC_SUCCESS);
8483 }
8484 
8485 /*@
8486    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8487      the matrix
8488 
8489    Neighbor-wise Collective
8490 
8491    Input Parameters:
8492 +  mat   - the matrix
8493 .  x - the vector to be multiplied by the interpolation operator
8494 -  y - the vector to be added to the result
8495 
8496    Output Parameter:
8497 .  w - the resulting vector
8498 
8499    Level: intermediate
8500 
8501    Notes:
8502     `w` may be the same vector as `y`.
8503 
8504     This allows one to use either the restriction or interpolation (its transpose)
8505     matrix to do the interpolation
8506 
8507 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8508 @*/
8509 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8510 {
8511   PetscInt M, N, Ny;
8512 
8513   PetscFunctionBegin;
8514   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8515   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8516   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8517   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8518   PetscCall(MatGetSize(A, &M, &N));
8519   PetscCall(VecGetSize(y, &Ny));
8520   if (M == Ny) {
8521     PetscCall(MatMultAdd(A, x, y, w));
8522   } else {
8523     PetscCall(MatMultTransposeAdd(A, x, y, w));
8524   }
8525   PetscFunctionReturn(PETSC_SUCCESS);
8526 }
8527 
8528 /*@
8529    MatInterpolate - y = A*x or A'*x depending on the shape of
8530      the matrix
8531 
8532    Neighbor-wise Collective
8533 
8534    Input Parameters:
8535 +  mat   - the matrix
8536 -  x - the vector to be interpolated
8537 
8538    Output Parameter:
8539 .  y - the resulting vector
8540 
8541    Level: intermediate
8542 
8543    Note:
8544     This allows one to use either the restriction or interpolation (its transpose)
8545     matrix to do the interpolation
8546 
8547 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8548 @*/
8549 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8550 {
8551   PetscInt M, N, Ny;
8552 
8553   PetscFunctionBegin;
8554   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8555   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8556   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8557   PetscCall(MatGetSize(A, &M, &N));
8558   PetscCall(VecGetSize(y, &Ny));
8559   if (M == Ny) {
8560     PetscCall(MatMult(A, x, y));
8561   } else {
8562     PetscCall(MatMultTranspose(A, x, y));
8563   }
8564   PetscFunctionReturn(PETSC_SUCCESS);
8565 }
8566 
8567 /*@
8568    MatRestrict - y = A*x or A'*x
8569 
8570    Neighbor-wise Collective
8571 
8572    Input Parameters:
8573 +  mat   - the matrix
8574 -  x - the vector to be restricted
8575 
8576    Output Parameter:
8577 .  y - the resulting vector
8578 
8579    Level: intermediate
8580 
8581    Note:
8582     This allows one to use either the restriction or interpolation (its transpose)
8583     matrix to do the restriction
8584 
8585 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8586 @*/
8587 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8588 {
8589   PetscInt M, N, Ny;
8590 
8591   PetscFunctionBegin;
8592   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8593   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8594   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8595   PetscCall(MatGetSize(A, &M, &N));
8596   PetscCall(VecGetSize(y, &Ny));
8597   if (M == Ny) {
8598     PetscCall(MatMult(A, x, y));
8599   } else {
8600     PetscCall(MatMultTranspose(A, x, y));
8601   }
8602   PetscFunctionReturn(PETSC_SUCCESS);
8603 }
8604 
8605 /*@
8606    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8607 
8608    Neighbor-wise Collective
8609 
8610    Input Parameters:
8611 +  mat   - the matrix
8612 .  x - the input dense matrix to be multiplied
8613 -  w - the input dense matrix to be added to the result
8614 
8615    Output Parameter:
8616 .  y - the output dense matrix
8617 
8618    Level: intermediate
8619 
8620    Note:
8621     This allows one to use either the restriction or interpolation (its transpose)
8622     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8623     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8624 
8625 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8626 @*/
8627 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8628 {
8629   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8630   PetscBool trans = PETSC_TRUE;
8631   MatReuse  reuse = MAT_INITIAL_MATRIX;
8632 
8633   PetscFunctionBegin;
8634   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8635   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8636   PetscValidType(x, 2);
8637   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8638   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8639   PetscCall(MatGetSize(A, &M, &N));
8640   PetscCall(MatGetSize(x, &Mx, &Nx));
8641   if (N == Mx) trans = PETSC_FALSE;
8642   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);
8643   Mo = trans ? N : M;
8644   if (*y) {
8645     PetscCall(MatGetSize(*y, &My, &Ny));
8646     if (Mo == My && Nx == Ny) {
8647       reuse = MAT_REUSE_MATRIX;
8648     } else {
8649       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);
8650       PetscCall(MatDestroy(y));
8651     }
8652   }
8653 
8654   if (w && *y == w) { /* this is to minimize changes in PCMG */
8655     PetscBool flg;
8656 
8657     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8658     if (w) {
8659       PetscInt My, Ny, Mw, Nw;
8660 
8661       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8662       PetscCall(MatGetSize(*y, &My, &Ny));
8663       PetscCall(MatGetSize(w, &Mw, &Nw));
8664       if (!flg || My != Mw || Ny != Nw) w = NULL;
8665     }
8666     if (!w) {
8667       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8668       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8669       PetscCall(PetscObjectDereference((PetscObject)w));
8670     } else {
8671       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8672     }
8673   }
8674   if (!trans) {
8675     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8676   } else {
8677     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8678   }
8679   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8680   PetscFunctionReturn(PETSC_SUCCESS);
8681 }
8682 
8683 /*@
8684    MatMatInterpolate - Y = A*X or A'*X
8685 
8686    Neighbor-wise Collective
8687 
8688    Input Parameters:
8689 +  mat   - the matrix
8690 -  x - the input dense matrix
8691 
8692    Output Parameter:
8693 .  y - the output dense matrix
8694 
8695    Level: intermediate
8696 
8697    Note:
8698     This allows one to use either the restriction or interpolation (its transpose)
8699     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8700     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8701 
8702 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8703 @*/
8704 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8705 {
8706   PetscFunctionBegin;
8707   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8708   PetscFunctionReturn(PETSC_SUCCESS);
8709 }
8710 
8711 /*@
8712    MatMatRestrict - Y = A*X or A'*X
8713 
8714    Neighbor-wise Collective
8715 
8716    Input Parameters:
8717 +  mat   - the matrix
8718 -  x - the input dense matrix
8719 
8720    Output Parameter:
8721 .  y - the output dense matrix
8722 
8723    Level: intermediate
8724 
8725    Note:
8726     This allows one to use either the restriction or interpolation (its transpose)
8727     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8728     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8729 
8730 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8731 @*/
8732 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8733 {
8734   PetscFunctionBegin;
8735   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8736   PetscFunctionReturn(PETSC_SUCCESS);
8737 }
8738 
8739 /*@
8740    MatGetNullSpace - retrieves the null space of a matrix.
8741 
8742    Logically Collective
8743 
8744    Input Parameters:
8745 +  mat - the matrix
8746 -  nullsp - the null space object
8747 
8748    Level: developer
8749 
8750 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8751 @*/
8752 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8753 {
8754   PetscFunctionBegin;
8755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8756   PetscValidPointer(nullsp, 2);
8757   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8758   PetscFunctionReturn(PETSC_SUCCESS);
8759 }
8760 
8761 /*@
8762    MatSetNullSpace - attaches a null space to a matrix.
8763 
8764    Logically Collective
8765 
8766    Input Parameters:
8767 +  mat - the matrix
8768 -  nullsp - the null space object
8769 
8770    Level: advanced
8771 
8772    Notes:
8773       This null space is used by the `KSP` linear solvers to solve singular systems.
8774 
8775       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`
8776 
8777       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
8778       to zero but the linear system will still be solved in a least squares sense.
8779 
8780       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8781    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).
8782    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
8783    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
8784    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).
8785    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8786 
8787     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8788     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8789     routine also automatically calls `MatSetTransposeNullSpace()`.
8790 
8791     The user should call `MatNullSpaceDestroy()`.
8792 
8793 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8794           `KSPSetPCSide()`
8795 @*/
8796 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8797 {
8798   PetscFunctionBegin;
8799   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8800   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8801   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8802   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8803   mat->nullsp = nullsp;
8804   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8805   PetscFunctionReturn(PETSC_SUCCESS);
8806 }
8807 
8808 /*@
8809    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8810 
8811    Logically Collective
8812 
8813    Input Parameters:
8814 +  mat - the matrix
8815 -  nullsp - the null space object
8816 
8817    Level: developer
8818 
8819 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8820 @*/
8821 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8822 {
8823   PetscFunctionBegin;
8824   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8825   PetscValidType(mat, 1);
8826   PetscValidPointer(nullsp, 2);
8827   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8828   PetscFunctionReturn(PETSC_SUCCESS);
8829 }
8830 
8831 /*@
8832    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8833 
8834    Logically Collective
8835 
8836    Input Parameters:
8837 +  mat - the matrix
8838 -  nullsp - the null space object
8839 
8840    Level: advanced
8841 
8842    Notes:
8843    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8844 
8845    See `MatSetNullSpace()`
8846 
8847 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8848 @*/
8849 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8850 {
8851   PetscFunctionBegin;
8852   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8853   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8854   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8855   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8856   mat->transnullsp = nullsp;
8857   PetscFunctionReturn(PETSC_SUCCESS);
8858 }
8859 
8860 /*@
8861    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8862         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8863 
8864    Logically Collective
8865 
8866    Input Parameters:
8867 +  mat - the matrix
8868 -  nullsp - the null space object
8869 
8870    Level: advanced
8871 
8872    Notes:
8873    Overwrites any previous near null space that may have been attached
8874 
8875    You can remove the null space by calling this routine with an nullsp of `NULL`
8876 
8877 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8878 @*/
8879 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8880 {
8881   PetscFunctionBegin;
8882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8883   PetscValidType(mat, 1);
8884   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8885   MatCheckPreallocated(mat, 1);
8886   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8887   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8888   mat->nearnullsp = nullsp;
8889   PetscFunctionReturn(PETSC_SUCCESS);
8890 }
8891 
8892 /*@
8893    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8894 
8895    Not Collective
8896 
8897    Input Parameter:
8898 .  mat - the matrix
8899 
8900    Output Parameter:
8901 .  nullsp - the null space object, `NULL` if not set
8902 
8903    Level: advanced
8904 
8905 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8906 @*/
8907 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8908 {
8909   PetscFunctionBegin;
8910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8911   PetscValidType(mat, 1);
8912   PetscValidPointer(nullsp, 2);
8913   MatCheckPreallocated(mat, 1);
8914   *nullsp = mat->nearnullsp;
8915   PetscFunctionReturn(PETSC_SUCCESS);
8916 }
8917 
8918 /*@C
8919    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8920 
8921    Collective
8922 
8923    Input Parameters:
8924 +  mat - the matrix
8925 .  row - row/column permutation
8926 -  info - information on desired factorization process
8927 
8928    Level: developer
8929 
8930    Notes:
8931    Probably really in-place only when level of fill is zero, otherwise allocates
8932    new space to store factored matrix and deletes previous memory.
8933 
8934    Most users should employ the `KSP` interface for linear solvers
8935    instead of working directly with matrix algebra routines such as this.
8936    See, e.g., `KSPCreate()`.
8937 
8938    Developer Note:
8939    The Fortran interface is not autogenerated as the
8940    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8941 
8942 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8943 @*/
8944 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8945 {
8946   PetscFunctionBegin;
8947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8948   PetscValidType(mat, 1);
8949   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8950   PetscValidPointer(info, 3);
8951   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8952   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8953   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8954   MatCheckPreallocated(mat, 1);
8955   PetscUseTypeMethod(mat, iccfactor, row, info);
8956   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8957   PetscFunctionReturn(PETSC_SUCCESS);
8958 }
8959 
8960 /*@
8961    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8962          ghosted ones.
8963 
8964    Not Collective
8965 
8966    Input Parameters:
8967 +  mat - the matrix
8968 -  diag - the diagonal values, including ghost ones
8969 
8970    Level: developer
8971 
8972    Notes:
8973     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8974 
8975     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8976 
8977 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8978 @*/
8979 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8980 {
8981   PetscMPIInt size;
8982 
8983   PetscFunctionBegin;
8984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8985   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8986   PetscValidType(mat, 1);
8987 
8988   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8989   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8990   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8991   if (size == 1) {
8992     PetscInt n, m;
8993     PetscCall(VecGetSize(diag, &n));
8994     PetscCall(MatGetSize(mat, NULL, &m));
8995     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8996     PetscCall(MatDiagonalScale(mat, NULL, diag));
8997   } else {
8998     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8999   }
9000   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9001   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9002   PetscFunctionReturn(PETSC_SUCCESS);
9003 }
9004 
9005 /*@
9006    MatGetInertia - Gets the inertia from a factored matrix
9007 
9008    Collective
9009 
9010    Input Parameter:
9011 .  mat - the matrix
9012 
9013    Output Parameters:
9014 +   nneg - number of negative eigenvalues
9015 .   nzero - number of zero eigenvalues
9016 -   npos - number of positive eigenvalues
9017 
9018    Level: advanced
9019 
9020    Note:
9021     Matrix must have been factored by `MatCholeskyFactor()`
9022 
9023 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9024 @*/
9025 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9026 {
9027   PetscFunctionBegin;
9028   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9029   PetscValidType(mat, 1);
9030   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9031   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9032   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9033   PetscFunctionReturn(PETSC_SUCCESS);
9034 }
9035 
9036 /*@C
9037    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9038 
9039    Neighbor-wise Collective
9040 
9041    Input Parameters:
9042 +  mat - the factored matrix obtained with `MatGetFactor()`
9043 -  b - the right-hand-side vectors
9044 
9045    Output Parameter:
9046 .  x - the result vectors
9047 
9048    Level: developer
9049 
9050    Note:
9051    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9052    call `MatSolves`(A,x,x).
9053 
9054 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9055 @*/
9056 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9057 {
9058   PetscFunctionBegin;
9059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9060   PetscValidType(mat, 1);
9061   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9062   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9063   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9064 
9065   MatCheckPreallocated(mat, 1);
9066   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9067   PetscUseTypeMethod(mat, solves, b, x);
9068   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9069   PetscFunctionReturn(PETSC_SUCCESS);
9070 }
9071 
9072 /*@
9073    MatIsSymmetric - Test whether a matrix is symmetric
9074 
9075    Collective
9076 
9077    Input Parameters:
9078 +  A - the matrix to test
9079 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9080 
9081    Output Parameter:
9082 .  flg - the result
9083 
9084    Level: intermediate
9085 
9086    Notes:
9087     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9088 
9089     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9090 
9091     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9092     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9093 
9094 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9095           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9096 @*/
9097 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9098 {
9099   PetscFunctionBegin;
9100   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9101   PetscValidBoolPointer(flg, 3);
9102 
9103   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9104   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9105   else {
9106     PetscUseTypeMethod(A, issymmetric, tol, flg);
9107     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9108   }
9109   PetscFunctionReturn(PETSC_SUCCESS);
9110 }
9111 
9112 /*@
9113    MatIsHermitian - Test whether a matrix is Hermitian
9114 
9115    Collective
9116 
9117    Input Parameters:
9118 +  A - the matrix to test
9119 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9120 
9121    Output Parameter:
9122 .  flg - the result
9123 
9124    Level: intermediate
9125 
9126    Notes:
9127     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9128 
9129     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9130 
9131     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9132     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9133 
9134 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9135           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9136 @*/
9137 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9138 {
9139   PetscFunctionBegin;
9140   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9141   PetscValidBoolPointer(flg, 3);
9142 
9143   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9144   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9145   else {
9146     PetscUseTypeMethod(A, ishermitian, tol, flg);
9147     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9148   }
9149   PetscFunctionReturn(PETSC_SUCCESS);
9150 }
9151 
9152 /*@
9153    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9154 
9155    Not Collective
9156 
9157    Input Parameter:
9158 .  A - the matrix to check
9159 
9160    Output Parameters:
9161 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9162 -  flg - the result (only valid if set is `PETSC_TRUE`)
9163 
9164    Level: advanced
9165 
9166    Notes:
9167    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9168    if you want it explicitly checked
9169 
9170     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9171     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9172 
9173 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9174 @*/
9175 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9176 {
9177   PetscFunctionBegin;
9178   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9179   PetscValidBoolPointer(set, 2);
9180   PetscValidBoolPointer(flg, 3);
9181   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9182     *set = PETSC_TRUE;
9183     *flg = PetscBool3ToBool(A->symmetric);
9184   } else {
9185     *set = PETSC_FALSE;
9186   }
9187   PetscFunctionReturn(PETSC_SUCCESS);
9188 }
9189 
9190 /*@
9191    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9192 
9193    Not Collective
9194 
9195    Input Parameter:
9196 .  A - the matrix to check
9197 
9198    Output Parameters:
9199 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9200 -  flg - the result (only valid if set is `PETSC_TRUE`)
9201 
9202    Level: advanced
9203 
9204    Notes:
9205    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9206 
9207    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9208    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9209 
9210 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9211 @*/
9212 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9213 {
9214   PetscFunctionBegin;
9215   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9216   PetscValidBoolPointer(set, 2);
9217   PetscValidBoolPointer(flg, 3);
9218   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9219     *set = PETSC_TRUE;
9220     *flg = PetscBool3ToBool(A->spd);
9221   } else {
9222     *set = PETSC_FALSE;
9223   }
9224   PetscFunctionReturn(PETSC_SUCCESS);
9225 }
9226 
9227 /*@
9228    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9229 
9230    Not Collective
9231 
9232    Input Parameter:
9233 .  A - the matrix to check
9234 
9235    Output Parameters:
9236 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9237 -  flg - the result (only valid if set is `PETSC_TRUE`)
9238 
9239    Level: advanced
9240 
9241    Notes:
9242    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9243    if you want it explicitly checked
9244 
9245    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9246    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9247 
9248 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9249 @*/
9250 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9251 {
9252   PetscFunctionBegin;
9253   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9254   PetscValidBoolPointer(set, 2);
9255   PetscValidBoolPointer(flg, 3);
9256   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9257     *set = PETSC_TRUE;
9258     *flg = PetscBool3ToBool(A->hermitian);
9259   } else {
9260     *set = PETSC_FALSE;
9261   }
9262   PetscFunctionReturn(PETSC_SUCCESS);
9263 }
9264 
9265 /*@
9266    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9267 
9268    Collective
9269 
9270    Input Parameter:
9271 .  A - the matrix to test
9272 
9273    Output Parameter:
9274 .  flg - the result
9275 
9276    Level: intermediate
9277 
9278    Notes:
9279    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9280 
9281    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
9282    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9283 
9284 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9285 @*/
9286 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9287 {
9288   PetscFunctionBegin;
9289   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9290   PetscValidBoolPointer(flg, 2);
9291   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9292     *flg = PetscBool3ToBool(A->structurally_symmetric);
9293   } else {
9294     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9295     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9296   }
9297   PetscFunctionReturn(PETSC_SUCCESS);
9298 }
9299 
9300 /*@
9301    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9302 
9303    Not Collective
9304 
9305    Input Parameter:
9306 .  A - the matrix to check
9307 
9308    Output Parameters:
9309 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9310 -  flg - the result (only valid if set is PETSC_TRUE)
9311 
9312    Level: advanced
9313 
9314    Notes:
9315    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
9316    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9317 
9318    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9319 
9320 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9321 @*/
9322 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9323 {
9324   PetscFunctionBegin;
9325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9326   PetscValidBoolPointer(set, 2);
9327   PetscValidBoolPointer(flg, 3);
9328   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9329     *set = PETSC_TRUE;
9330     *flg = PetscBool3ToBool(A->structurally_symmetric);
9331   } else {
9332     *set = PETSC_FALSE;
9333   }
9334   PetscFunctionReturn(PETSC_SUCCESS);
9335 }
9336 
9337 /*@
9338    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9339        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9340 
9341     Not Collective
9342 
9343    Input Parameter:
9344 .   mat - the matrix
9345 
9346    Output Parameters:
9347 +   nstash   - the size of the stash
9348 .   reallocs - the number of additional mallocs incurred.
9349 .   bnstash   - the size of the block stash
9350 -   breallocs - the number of additional mallocs incurred.in the block stash
9351 
9352    Level: advanced
9353 
9354 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9355 @*/
9356 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9357 {
9358   PetscFunctionBegin;
9359   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9360   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9361   PetscFunctionReturn(PETSC_SUCCESS);
9362 }
9363 
9364 /*@C
9365    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9366    parallel layout, `PetscLayout` for rows and columns
9367 
9368    Collective
9369 
9370    Input Parameter:
9371 .  mat - the matrix
9372 
9373    Output Parameters:
9374 +   right - (optional) vector that the matrix can be multiplied against
9375 -   left - (optional) vector that the matrix vector product can be stored in
9376 
9377   Level: advanced
9378 
9379    Notes:
9380     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()`.
9381 
9382     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9383 
9384 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9385 @*/
9386 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9387 {
9388   PetscFunctionBegin;
9389   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9390   PetscValidType(mat, 1);
9391   if (mat->ops->getvecs) {
9392     PetscUseTypeMethod(mat, getvecs, right, left);
9393   } else {
9394     PetscInt rbs, cbs;
9395     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9396     if (right) {
9397       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9398       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9399       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9400       PetscCall(VecSetBlockSize(*right, cbs));
9401       PetscCall(VecSetType(*right, mat->defaultvectype));
9402 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9403       if (mat->boundtocpu && mat->bindingpropagates) {
9404         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9405         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9406       }
9407 #endif
9408       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9409     }
9410     if (left) {
9411       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9412       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9413       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9414       PetscCall(VecSetBlockSize(*left, rbs));
9415       PetscCall(VecSetType(*left, mat->defaultvectype));
9416 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9417       if (mat->boundtocpu && mat->bindingpropagates) {
9418         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9419         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9420       }
9421 #endif
9422       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9423     }
9424   }
9425   PetscFunctionReturn(PETSC_SUCCESS);
9426 }
9427 
9428 /*@C
9429    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9430      with default values.
9431 
9432    Not Collective
9433 
9434    Input Parameter:
9435 .    info - the `MatFactorInfo` data structure
9436 
9437    Level: developer
9438 
9439    Notes:
9440     The solvers are generally used through the `KSP` and `PC` objects, for example
9441           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9442 
9443     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9444 
9445    Developer Note:
9446    The Fortran interface is not autogenerated as the
9447    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9448 
9449 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9450 @*/
9451 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9452 {
9453   PetscFunctionBegin;
9454   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9455   PetscFunctionReturn(PETSC_SUCCESS);
9456 }
9457 
9458 /*@
9459    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9460 
9461    Collective
9462 
9463    Input Parameters:
9464 +  mat - the factored matrix
9465 -  is - the index set defining the Schur indices (0-based)
9466 
9467    Level: advanced
9468 
9469    Notes:
9470     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9471 
9472    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9473 
9474    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9475 
9476 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9477           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9478 @*/
9479 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9480 {
9481   PetscErrorCode (*f)(Mat, IS);
9482 
9483   PetscFunctionBegin;
9484   PetscValidType(mat, 1);
9485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9486   PetscValidType(is, 2);
9487   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9488   PetscCheckSameComm(mat, 1, is, 2);
9489   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9490   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9491   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9492   PetscCall(MatDestroy(&mat->schur));
9493   PetscCall((*f)(mat, is));
9494   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9495   PetscFunctionReturn(PETSC_SUCCESS);
9496 }
9497 
9498 /*@
9499   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9500 
9501    Logically Collective
9502 
9503    Input Parameters:
9504 +  F - the factored matrix obtained by calling `MatGetFactor()`
9505 .  S - location where to return the Schur complement, can be `NULL`
9506 -  status - the status of the Schur complement matrix, can be `NULL`
9507 
9508    Level: advanced
9509 
9510    Notes:
9511    You must call `MatFactorSetSchurIS()` before calling this routine.
9512 
9513    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9514 
9515    The routine provides a copy of the Schur matrix stored within the solver data structures.
9516    The caller must destroy the object when it is no longer needed.
9517    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9518 
9519    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)
9520 
9521    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9522 
9523    Developer Note:
9524     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9525    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9526 
9527 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9528 @*/
9529 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9530 {
9531   PetscFunctionBegin;
9532   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9533   if (S) PetscValidPointer(S, 2);
9534   if (status) PetscValidPointer(status, 3);
9535   if (S) {
9536     PetscErrorCode (*f)(Mat, Mat *);
9537 
9538     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9539     if (f) {
9540       PetscCall((*f)(F, S));
9541     } else {
9542       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9543     }
9544   }
9545   if (status) *status = F->schur_status;
9546   PetscFunctionReturn(PETSC_SUCCESS);
9547 }
9548 
9549 /*@
9550   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9551 
9552    Logically Collective
9553 
9554    Input Parameters:
9555 +  F - the factored matrix obtained by calling `MatGetFactor()`
9556 .  *S - location where to return the Schur complement, can be `NULL`
9557 -  status - the status of the Schur complement matrix, can be `NULL`
9558 
9559    Level: advanced
9560 
9561    Notes:
9562    You must call `MatFactorSetSchurIS()` before calling this routine.
9563 
9564    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9565 
9566    The routine returns a the Schur Complement stored within the data structures of the solver.
9567 
9568    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9569 
9570    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9571 
9572    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9573 
9574    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9575 
9576 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9577 @*/
9578 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9579 {
9580   PetscFunctionBegin;
9581   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9582   if (S) PetscValidPointer(S, 2);
9583   if (status) PetscValidPointer(status, 3);
9584   if (S) *S = F->schur;
9585   if (status) *status = F->schur_status;
9586   PetscFunctionReturn(PETSC_SUCCESS);
9587 }
9588 
9589 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9590 {
9591   Mat S = F->schur;
9592 
9593   PetscFunctionBegin;
9594   switch (F->schur_status) {
9595   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9596   case MAT_FACTOR_SCHUR_INVERTED:
9597     if (S) {
9598       S->ops->solve             = NULL;
9599       S->ops->matsolve          = NULL;
9600       S->ops->solvetranspose    = NULL;
9601       S->ops->matsolvetranspose = NULL;
9602       S->ops->solveadd          = NULL;
9603       S->ops->solvetransposeadd = NULL;
9604       S->factortype             = MAT_FACTOR_NONE;
9605       PetscCall(PetscFree(S->solvertype));
9606     }
9607   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9608     break;
9609   default:
9610     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9611   }
9612   PetscFunctionReturn(PETSC_SUCCESS);
9613 }
9614 
9615 /*@
9616   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9617 
9618    Logically Collective
9619 
9620    Input Parameters:
9621 +  F - the factored matrix obtained by calling `MatGetFactor()`
9622 .  *S - location where the Schur complement is stored
9623 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9624 
9625    Level: advanced
9626 
9627 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9628 @*/
9629 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9630 {
9631   PetscFunctionBegin;
9632   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9633   if (S) {
9634     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9635     *S = NULL;
9636   }
9637   F->schur_status = status;
9638   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9639   PetscFunctionReturn(PETSC_SUCCESS);
9640 }
9641 
9642 /*@
9643   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9644 
9645    Logically Collective
9646 
9647    Input Parameters:
9648 +  F - the factored matrix obtained by calling `MatGetFactor()`
9649 .  rhs - location where the right hand side of the Schur complement system is stored
9650 -  sol - location where the solution of the Schur complement system has to be returned
9651 
9652    Level: advanced
9653 
9654    Notes:
9655    The sizes of the vectors should match the size of the Schur complement
9656 
9657    Must be called after `MatFactorSetSchurIS()`
9658 
9659 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9660 @*/
9661 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9662 {
9663   PetscFunctionBegin;
9664   PetscValidType(F, 1);
9665   PetscValidType(rhs, 2);
9666   PetscValidType(sol, 3);
9667   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9668   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9669   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9670   PetscCheckSameComm(F, 1, rhs, 2);
9671   PetscCheckSameComm(F, 1, sol, 3);
9672   PetscCall(MatFactorFactorizeSchurComplement(F));
9673   switch (F->schur_status) {
9674   case MAT_FACTOR_SCHUR_FACTORED:
9675     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9676     break;
9677   case MAT_FACTOR_SCHUR_INVERTED:
9678     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9679     break;
9680   default:
9681     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9682   }
9683   PetscFunctionReturn(PETSC_SUCCESS);
9684 }
9685 
9686 /*@
9687   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9688 
9689    Logically Collective
9690 
9691    Input Parameters:
9692 +  F - the factored matrix obtained by calling `MatGetFactor()`
9693 .  rhs - location where the right hand side of the Schur complement system is stored
9694 -  sol - location where the solution of the Schur complement system has to be returned
9695 
9696    Level: advanced
9697 
9698    Notes:
9699    The sizes of the vectors should match the size of the Schur complement
9700 
9701    Must be called after `MatFactorSetSchurIS()`
9702 
9703 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9704 @*/
9705 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9706 {
9707   PetscFunctionBegin;
9708   PetscValidType(F, 1);
9709   PetscValidType(rhs, 2);
9710   PetscValidType(sol, 3);
9711   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9712   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9713   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9714   PetscCheckSameComm(F, 1, rhs, 2);
9715   PetscCheckSameComm(F, 1, sol, 3);
9716   PetscCall(MatFactorFactorizeSchurComplement(F));
9717   switch (F->schur_status) {
9718   case MAT_FACTOR_SCHUR_FACTORED:
9719     PetscCall(MatSolve(F->schur, rhs, sol));
9720     break;
9721   case MAT_FACTOR_SCHUR_INVERTED:
9722     PetscCall(MatMult(F->schur, rhs, sol));
9723     break;
9724   default:
9725     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9726   }
9727   PetscFunctionReturn(PETSC_SUCCESS);
9728 }
9729 
9730 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9731 #if PetscDefined(HAVE_CUDA)
9732 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9733 #endif
9734 
9735 /* Schur status updated in the interface */
9736 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9737 {
9738   Mat S = F->schur;
9739 
9740   PetscFunctionBegin;
9741   if (S) {
9742     PetscMPIInt size;
9743     PetscBool   isdense, isdensecuda;
9744 
9745     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9746     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9747     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9748     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9749     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9750     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9751     if (isdense) {
9752       PetscCall(MatSeqDenseInvertFactors_Private(S));
9753     } else if (isdensecuda) {
9754 #if defined(PETSC_HAVE_CUDA)
9755       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9756 #endif
9757     }
9758     // HIP??????????????
9759     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9760   }
9761   PetscFunctionReturn(PETSC_SUCCESS);
9762 }
9763 
9764 /*@
9765   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9766 
9767    Logically Collective
9768 
9769    Input Parameter:
9770 .  F - the factored matrix obtained by calling `MatGetFactor()`
9771 
9772    Level: advanced
9773 
9774    Notes:
9775     Must be called after `MatFactorSetSchurIS()`.
9776 
9777    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9778 
9779 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9780 @*/
9781 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9782 {
9783   PetscFunctionBegin;
9784   PetscValidType(F, 1);
9785   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9786   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9787   PetscCall(MatFactorFactorizeSchurComplement(F));
9788   PetscCall(MatFactorInvertSchurComplement_Private(F));
9789   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9790   PetscFunctionReturn(PETSC_SUCCESS);
9791 }
9792 
9793 /*@
9794   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9795 
9796    Logically Collective
9797 
9798    Input Parameter:
9799 .  F - the factored matrix obtained by calling `MatGetFactor()`
9800 
9801    Level: advanced
9802 
9803    Note:
9804     Must be called after `MatFactorSetSchurIS()`
9805 
9806 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9807 @*/
9808 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9809 {
9810   MatFactorInfo info;
9811 
9812   PetscFunctionBegin;
9813   PetscValidType(F, 1);
9814   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9815   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9816   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9817   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9818   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9819     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9820   } else {
9821     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9822   }
9823   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9824   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9825   PetscFunctionReturn(PETSC_SUCCESS);
9826 }
9827 
9828 /*@
9829    MatPtAP - Creates the matrix product C = P^T * A * P
9830 
9831    Neighbor-wise Collective
9832 
9833    Input Parameters:
9834 +  A - the matrix
9835 .  P - the projection matrix
9836 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9837 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9838           if the result is a dense matrix this is irrelevant
9839 
9840    Output Parameter:
9841 .  C - the product matrix
9842 
9843    Level: intermediate
9844 
9845    Notes:
9846    C will be created and must be destroyed by the user with `MatDestroy()`.
9847 
9848    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9849 
9850    Developer Note:
9851    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9852 
9853 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9854 @*/
9855 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9856 {
9857   PetscFunctionBegin;
9858   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9859   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9860 
9861   if (scall == MAT_INITIAL_MATRIX) {
9862     PetscCall(MatProductCreate(A, P, NULL, C));
9863     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9864     PetscCall(MatProductSetAlgorithm(*C, "default"));
9865     PetscCall(MatProductSetFill(*C, fill));
9866 
9867     (*C)->product->api_user = PETSC_TRUE;
9868     PetscCall(MatProductSetFromOptions(*C));
9869     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);
9870     PetscCall(MatProductSymbolic(*C));
9871   } else { /* scall == MAT_REUSE_MATRIX */
9872     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9873   }
9874 
9875   PetscCall(MatProductNumeric(*C));
9876   (*C)->symmetric = A->symmetric;
9877   (*C)->spd       = A->spd;
9878   PetscFunctionReturn(PETSC_SUCCESS);
9879 }
9880 
9881 /*@
9882    MatRARt - Creates the matrix product C = R * A * R^T
9883 
9884    Neighbor-wise Collective
9885 
9886    Input Parameters:
9887 +  A - the matrix
9888 .  R - the projection matrix
9889 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9890 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9891           if the result is a dense matrix this is irrelevant
9892 
9893    Output Parameter:
9894 .  C - the product matrix
9895 
9896    Level: intermediate
9897 
9898    Notes:
9899    C will be created and must be destroyed by the user with `MatDestroy()`.
9900 
9901    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9902 
9903    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9904    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9905    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9906    We recommend using MatPtAP().
9907 
9908 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9909 @*/
9910 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9911 {
9912   PetscFunctionBegin;
9913   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9914   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9915 
9916   if (scall == MAT_INITIAL_MATRIX) {
9917     PetscCall(MatProductCreate(A, R, NULL, C));
9918     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9919     PetscCall(MatProductSetAlgorithm(*C, "default"));
9920     PetscCall(MatProductSetFill(*C, fill));
9921 
9922     (*C)->product->api_user = PETSC_TRUE;
9923     PetscCall(MatProductSetFromOptions(*C));
9924     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);
9925     PetscCall(MatProductSymbolic(*C));
9926   } else { /* scall == MAT_REUSE_MATRIX */
9927     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9928   }
9929 
9930   PetscCall(MatProductNumeric(*C));
9931   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9932   PetscFunctionReturn(PETSC_SUCCESS);
9933 }
9934 
9935 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9936 {
9937   PetscFunctionBegin;
9938   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9939 
9940   if (scall == MAT_INITIAL_MATRIX) {
9941     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9942     PetscCall(MatProductCreate(A, B, NULL, C));
9943     PetscCall(MatProductSetType(*C, ptype));
9944     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9945     PetscCall(MatProductSetFill(*C, fill));
9946 
9947     (*C)->product->api_user = PETSC_TRUE;
9948     PetscCall(MatProductSetFromOptions(*C));
9949     PetscCall(MatProductSymbolic(*C));
9950   } else { /* scall == MAT_REUSE_MATRIX */
9951     Mat_Product *product = (*C)->product;
9952     PetscBool    isdense;
9953 
9954     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9955     if (isdense && product && product->type != ptype) {
9956       PetscCall(MatProductClear(*C));
9957       product = NULL;
9958     }
9959     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9960     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9961       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9962       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9963       product           = (*C)->product;
9964       product->fill     = fill;
9965       product->api_user = PETSC_TRUE;
9966       product->clear    = PETSC_TRUE;
9967 
9968       PetscCall(MatProductSetType(*C, ptype));
9969       PetscCall(MatProductSetFromOptions(*C));
9970       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);
9971       PetscCall(MatProductSymbolic(*C));
9972     } else { /* user may change input matrices A or B when REUSE */
9973       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9974     }
9975   }
9976   PetscCall(MatProductNumeric(*C));
9977   PetscFunctionReturn(PETSC_SUCCESS);
9978 }
9979 
9980 /*@
9981    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9982 
9983    Neighbor-wise Collective
9984 
9985    Input Parameters:
9986 +  A - the left matrix
9987 .  B - the right matrix
9988 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9989 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9990           if the result is a dense matrix this is irrelevant
9991 
9992    Output Parameter:
9993 .  C - the product matrix
9994 
9995    Notes:
9996    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9997 
9998    `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
9999    call to this function with `MAT_INITIAL_MATRIX`.
10000 
10001    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10002 
10003    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`,
10004    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10005 
10006    Example of Usage:
10007 .vb
10008      MatProductCreate(A,B,NULL,&C);
10009      MatProductSetType(C,MATPRODUCT_AB);
10010      MatProductSymbolic(C);
10011      MatProductNumeric(C); // compute C=A * B
10012      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10013      MatProductNumeric(C);
10014      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10015      MatProductNumeric(C);
10016 .ve
10017 
10018    Level: intermediate
10019 
10020 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10021 @*/
10022 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10023 {
10024   PetscFunctionBegin;
10025   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10026   PetscFunctionReturn(PETSC_SUCCESS);
10027 }
10028 
10029 /*@
10030    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10031 
10032    Neighbor-wise Collective
10033 
10034    Input Parameters:
10035 +  A - the left matrix
10036 .  B - the right matrix
10037 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10038 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10039 
10040    Output Parameter:
10041 .  C - the product matrix
10042 
10043    Level: intermediate
10044 
10045    Notes:
10046    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10047 
10048    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10049 
10050    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10051    actually needed.
10052 
10053    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10054    and for pairs of `MATMPIDENSE` matrices.
10055 
10056    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10057 
10058    Options Database Keys:
10059 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10060               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10061               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10062 
10063 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10064 @*/
10065 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10066 {
10067   PetscFunctionBegin;
10068   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10069   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10070   PetscFunctionReturn(PETSC_SUCCESS);
10071 }
10072 
10073 /*@
10074    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10075 
10076    Neighbor-wise Collective
10077 
10078    Input Parameters:
10079 +  A - the left matrix
10080 .  B - the right matrix
10081 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10082 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10083 
10084    Output Parameter:
10085 .  C - the product matrix
10086 
10087    Level: intermediate
10088 
10089    Notes:
10090    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10091 
10092    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10093 
10094    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10095 
10096    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10097    actually needed.
10098 
10099    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10100    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10101 
10102 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10103 @*/
10104 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10105 {
10106   PetscFunctionBegin;
10107   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10108   PetscFunctionReturn(PETSC_SUCCESS);
10109 }
10110 
10111 /*@
10112    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10113 
10114    Neighbor-wise Collective
10115 
10116    Input Parameters:
10117 +  A - the left matrix
10118 .  B - the middle matrix
10119 .  C - the right matrix
10120 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10121 -  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
10122           if the result is a dense matrix this is irrelevant
10123 
10124    Output Parameter:
10125 .  D - the product matrix
10126 
10127    Level: intermediate
10128 
10129    Notes:
10130    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10131 
10132    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10133 
10134    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10135 
10136    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10137    actually needed.
10138 
10139    If you have many matrices with the same non-zero structure to multiply, you
10140    should use `MAT_REUSE_MATRIX` in all calls but the first
10141 
10142 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10143 @*/
10144 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10145 {
10146   PetscFunctionBegin;
10147   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10148   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10149 
10150   if (scall == MAT_INITIAL_MATRIX) {
10151     PetscCall(MatProductCreate(A, B, C, D));
10152     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10153     PetscCall(MatProductSetAlgorithm(*D, "default"));
10154     PetscCall(MatProductSetFill(*D, fill));
10155 
10156     (*D)->product->api_user = PETSC_TRUE;
10157     PetscCall(MatProductSetFromOptions(*D));
10158     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,
10159                ((PetscObject)C)->type_name);
10160     PetscCall(MatProductSymbolic(*D));
10161   } else { /* user may change input matrices when REUSE */
10162     PetscCall(MatProductReplaceMats(A, B, C, *D));
10163   }
10164   PetscCall(MatProductNumeric(*D));
10165   PetscFunctionReturn(PETSC_SUCCESS);
10166 }
10167 
10168 /*@
10169    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10170 
10171    Collective
10172 
10173    Input Parameters:
10174 +  mat - the matrix
10175 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10176 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10177 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10178 
10179    Output Parameter:
10180 .  matredundant - redundant matrix
10181 
10182    Level: advanced
10183 
10184    Notes:
10185    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10186    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10187 
10188    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10189    calling it.
10190 
10191    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10192 
10193 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10194 @*/
10195 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10196 {
10197   MPI_Comm       comm;
10198   PetscMPIInt    size;
10199   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10200   Mat_Redundant *redund     = NULL;
10201   PetscSubcomm   psubcomm   = NULL;
10202   MPI_Comm       subcomm_in = subcomm;
10203   Mat           *matseq;
10204   IS             isrow, iscol;
10205   PetscBool      newsubcomm = PETSC_FALSE;
10206 
10207   PetscFunctionBegin;
10208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10209   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10210     PetscValidPointer(*matredundant, 5);
10211     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10212   }
10213 
10214   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10215   if (size == 1 || nsubcomm == 1) {
10216     if (reuse == MAT_INITIAL_MATRIX) {
10217       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10218     } else {
10219       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");
10220       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10221     }
10222     PetscFunctionReturn(PETSC_SUCCESS);
10223   }
10224 
10225   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10226   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10227   MatCheckPreallocated(mat, 1);
10228 
10229   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10230   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10231     /* create psubcomm, then get subcomm */
10232     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10233     PetscCallMPI(MPI_Comm_size(comm, &size));
10234     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10235 
10236     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10237     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10238     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10239     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10240     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10241     newsubcomm = PETSC_TRUE;
10242     PetscCall(PetscSubcommDestroy(&psubcomm));
10243   }
10244 
10245   /* get isrow, iscol and a local sequential matrix matseq[0] */
10246   if (reuse == MAT_INITIAL_MATRIX) {
10247     mloc_sub = PETSC_DECIDE;
10248     nloc_sub = PETSC_DECIDE;
10249     if (bs < 1) {
10250       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10251       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10252     } else {
10253       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10254       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10255     }
10256     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10257     rstart = rend - mloc_sub;
10258     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10259     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10260   } else { /* reuse == MAT_REUSE_MATRIX */
10261     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");
10262     /* retrieve subcomm */
10263     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10264     redund = (*matredundant)->redundant;
10265     isrow  = redund->isrow;
10266     iscol  = redund->iscol;
10267     matseq = redund->matseq;
10268   }
10269   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10270 
10271   /* get matredundant over subcomm */
10272   if (reuse == MAT_INITIAL_MATRIX) {
10273     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10274 
10275     /* create a supporting struct and attach it to C for reuse */
10276     PetscCall(PetscNew(&redund));
10277     (*matredundant)->redundant = redund;
10278     redund->isrow              = isrow;
10279     redund->iscol              = iscol;
10280     redund->matseq             = matseq;
10281     if (newsubcomm) {
10282       redund->subcomm = subcomm;
10283     } else {
10284       redund->subcomm = MPI_COMM_NULL;
10285     }
10286   } else {
10287     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10288   }
10289 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10290   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10291     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10292     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10293   }
10294 #endif
10295   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10296   PetscFunctionReturn(PETSC_SUCCESS);
10297 }
10298 
10299 /*@C
10300    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10301    a given `Mat`. Each submatrix can span multiple procs.
10302 
10303    Collective
10304 
10305    Input Parameters:
10306 +  mat - the matrix
10307 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10308 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10309 
10310    Output Parameter:
10311 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10312 
10313   Level: advanced
10314 
10315   Notes:
10316   The submatrix partition across processors is dictated by `subComm` a
10317   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10318   is not restricted to be grouped with consecutive original ranks.
10319 
10320   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10321   map directly to the layout of the original matrix [wrt the local
10322   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10323   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10324   the `subMat`. However the offDiagMat looses some columns - and this is
10325   reconstructed with `MatSetValues()`
10326 
10327   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10328 
10329 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10330 @*/
10331 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10332 {
10333   PetscMPIInt commsize, subCommSize;
10334 
10335   PetscFunctionBegin;
10336   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10337   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10338   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10339 
10340   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");
10341   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10342   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10343   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10344   PetscFunctionReturn(PETSC_SUCCESS);
10345 }
10346 
10347 /*@
10348    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10349 
10350    Not Collective
10351 
10352    Input Parameters:
10353 +  mat - matrix to extract local submatrix from
10354 .  isrow - local row indices for submatrix
10355 -  iscol - local column indices for submatrix
10356 
10357    Output Parameter:
10358 .  submat - the submatrix
10359 
10360    Level: intermediate
10361 
10362    Notes:
10363    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10364 
10365    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10366    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10367 
10368    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10369    `MatSetValuesBlockedLocal()` will also be implemented.
10370 
10371    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10372    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10373 
10374 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10375 @*/
10376 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10377 {
10378   PetscFunctionBegin;
10379   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10380   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10381   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10382   PetscCheckSameComm(isrow, 2, iscol, 3);
10383   PetscValidPointer(submat, 4);
10384   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10385 
10386   if (mat->ops->getlocalsubmatrix) {
10387     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10388   } else {
10389     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10390   }
10391   PetscFunctionReturn(PETSC_SUCCESS);
10392 }
10393 
10394 /*@
10395    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10396 
10397    Not Collective
10398 
10399    Input Parameters:
10400 +  mat - matrix to extract local submatrix from
10401 .  isrow - local row indices for submatrix
10402 .  iscol - local column indices for submatrix
10403 -  submat - the submatrix
10404 
10405    Level: intermediate
10406 
10407 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10408 @*/
10409 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10410 {
10411   PetscFunctionBegin;
10412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10413   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10414   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10415   PetscCheckSameComm(isrow, 2, iscol, 3);
10416   PetscValidPointer(submat, 4);
10417   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10418 
10419   if (mat->ops->restorelocalsubmatrix) {
10420     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10421   } else {
10422     PetscCall(MatDestroy(submat));
10423   }
10424   *submat = NULL;
10425   PetscFunctionReturn(PETSC_SUCCESS);
10426 }
10427 
10428 /*@
10429    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10430 
10431    Collective
10432 
10433    Input Parameter:
10434 .  mat - the matrix
10435 
10436    Output Parameter:
10437 .  is - if any rows have zero diagonals this contains the list of them
10438 
10439    Level: developer
10440 
10441 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10442 @*/
10443 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10444 {
10445   PetscFunctionBegin;
10446   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10447   PetscValidType(mat, 1);
10448   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10449   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10450 
10451   if (!mat->ops->findzerodiagonals) {
10452     Vec                diag;
10453     const PetscScalar *a;
10454     PetscInt          *rows;
10455     PetscInt           rStart, rEnd, r, nrow = 0;
10456 
10457     PetscCall(MatCreateVecs(mat, &diag, NULL));
10458     PetscCall(MatGetDiagonal(mat, diag));
10459     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10460     PetscCall(VecGetArrayRead(diag, &a));
10461     for (r = 0; r < rEnd - rStart; ++r)
10462       if (a[r] == 0.0) ++nrow;
10463     PetscCall(PetscMalloc1(nrow, &rows));
10464     nrow = 0;
10465     for (r = 0; r < rEnd - rStart; ++r)
10466       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10467     PetscCall(VecRestoreArrayRead(diag, &a));
10468     PetscCall(VecDestroy(&diag));
10469     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10470   } else {
10471     PetscUseTypeMethod(mat, findzerodiagonals, is);
10472   }
10473   PetscFunctionReturn(PETSC_SUCCESS);
10474 }
10475 
10476 /*@
10477    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10478 
10479    Collective
10480 
10481    Input Parameter:
10482 .  mat - the matrix
10483 
10484    Output Parameter:
10485 .  is - contains the list of rows with off block diagonal entries
10486 
10487    Level: developer
10488 
10489 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10490 @*/
10491 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10492 {
10493   PetscFunctionBegin;
10494   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10495   PetscValidType(mat, 1);
10496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10498 
10499   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10500   PetscFunctionReturn(PETSC_SUCCESS);
10501 }
10502 
10503 /*@C
10504   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10505 
10506   Collective; No Fortran Support
10507 
10508   Input Parameter:
10509 . mat - the matrix
10510 
10511   Output Parameter:
10512 . values - the block inverses in column major order (FORTRAN-like)
10513 
10514   Level: advanced
10515 
10516    Notes:
10517    The size of the blocks is determined by the block size of the matrix.
10518 
10519    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10520 
10521    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10522 
10523 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10524 @*/
10525 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10526 {
10527   PetscFunctionBegin;
10528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10529   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10530   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10531   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10532   PetscFunctionReturn(PETSC_SUCCESS);
10533 }
10534 
10535 /*@C
10536   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10537 
10538   Collective; No Fortran Support
10539 
10540   Input Parameters:
10541 + mat - the matrix
10542 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10543 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10544 
10545   Output Parameter:
10546 . values - the block inverses in column major order (FORTRAN-like)
10547 
10548   Level: advanced
10549 
10550   Notes:
10551   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10552 
10553   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10554 
10555 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10556 @*/
10557 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10558 {
10559   PetscFunctionBegin;
10560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10561   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10562   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10563   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10564   PetscFunctionReturn(PETSC_SUCCESS);
10565 }
10566 
10567 /*@
10568   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10569 
10570   Collective
10571 
10572   Input Parameters:
10573 + A - the matrix
10574 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10575 
10576   Level: advanced
10577 
10578   Note:
10579   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10580 
10581 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10582 @*/
10583 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10584 {
10585   const PetscScalar *vals;
10586   PetscInt          *dnnz;
10587   PetscInt           m, rstart, rend, bs, i, j;
10588 
10589   PetscFunctionBegin;
10590   PetscCall(MatInvertBlockDiagonal(A, &vals));
10591   PetscCall(MatGetBlockSize(A, &bs));
10592   PetscCall(MatGetLocalSize(A, &m, NULL));
10593   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10594   PetscCall(PetscMalloc1(m / bs, &dnnz));
10595   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10596   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10597   PetscCall(PetscFree(dnnz));
10598   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10599   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10600   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10601   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10602   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10603   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10604   PetscFunctionReturn(PETSC_SUCCESS);
10605 }
10606 
10607 /*@C
10608     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10609     via `MatTransposeColoringCreate()`.
10610 
10611     Collective
10612 
10613     Input Parameter:
10614 .   c - coloring context
10615 
10616     Level: intermediate
10617 
10618 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10619 @*/
10620 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10621 {
10622   MatTransposeColoring matcolor = *c;
10623 
10624   PetscFunctionBegin;
10625   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10626   if (--((PetscObject)matcolor)->refct > 0) {
10627     matcolor = NULL;
10628     PetscFunctionReturn(PETSC_SUCCESS);
10629   }
10630 
10631   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10632   PetscCall(PetscFree(matcolor->rows));
10633   PetscCall(PetscFree(matcolor->den2sp));
10634   PetscCall(PetscFree(matcolor->colorforcol));
10635   PetscCall(PetscFree(matcolor->columns));
10636   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10637   PetscCall(PetscHeaderDestroy(c));
10638   PetscFunctionReturn(PETSC_SUCCESS);
10639 }
10640 
10641 /*@C
10642     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10643     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10644     `MatTransposeColoring` to sparse B.
10645 
10646     Collective
10647 
10648     Input Parameters:
10649 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10650 -   B - sparse matrix
10651 
10652     Output Parameter:
10653 .   Btdense - dense matrix B^T
10654 
10655     Level: developer
10656 
10657     Note:
10658     These are used internally for some implementations of `MatRARt()`
10659 
10660 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10661 @*/
10662 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10663 {
10664   PetscFunctionBegin;
10665   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10666   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10667   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10668 
10669   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10670   PetscFunctionReturn(PETSC_SUCCESS);
10671 }
10672 
10673 /*@C
10674     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10675     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10676     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10677     `Csp` from `Cden`.
10678 
10679     Collective
10680 
10681     Input Parameters:
10682 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10683 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10684 
10685     Output Parameter:
10686 .   Csp - sparse matrix
10687 
10688     Level: developer
10689 
10690     Note:
10691     These are used internally for some implementations of `MatRARt()`
10692 
10693 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10694 @*/
10695 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10696 {
10697   PetscFunctionBegin;
10698   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10699   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10700   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10701 
10702   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10703   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10704   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10705   PetscFunctionReturn(PETSC_SUCCESS);
10706 }
10707 
10708 /*@C
10709    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10710 
10711    Collective
10712 
10713    Input Parameters:
10714 +  mat - the matrix product C
10715 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10716 
10717     Output Parameter:
10718 .   color - the new coloring context
10719 
10720     Level: intermediate
10721 
10722 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10723           `MatTransColoringApplyDenToSp()`
10724 @*/
10725 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10726 {
10727   MatTransposeColoring c;
10728   MPI_Comm             comm;
10729 
10730   PetscFunctionBegin;
10731   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10732   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10733   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10734 
10735   c->ctype = iscoloring->ctype;
10736   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10737 
10738   *color = c;
10739   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10740   PetscFunctionReturn(PETSC_SUCCESS);
10741 }
10742 
10743 /*@
10744       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10745         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10746         same, otherwise it will be larger
10747 
10748      Not Collective
10749 
10750   Input Parameter:
10751 .    A  - the matrix
10752 
10753   Output Parameter:
10754 .    state - the current state
10755 
10756   Level: intermediate
10757 
10758   Notes:
10759     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10760          different matrices
10761 
10762     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10763 
10764     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10765 
10766 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10767 @*/
10768 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10769 {
10770   PetscFunctionBegin;
10771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10772   *state = mat->nonzerostate;
10773   PetscFunctionReturn(PETSC_SUCCESS);
10774 }
10775 
10776 /*@
10777       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10778                  matrices from each processor
10779 
10780     Collective
10781 
10782    Input Parameters:
10783 +    comm - the communicators the parallel matrix will live on
10784 .    seqmat - the input sequential matrices
10785 .    n - number of local columns (or `PETSC_DECIDE`)
10786 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10787 
10788    Output Parameter:
10789 .    mpimat - the parallel matrix generated
10790 
10791     Level: developer
10792 
10793    Note:
10794     The number of columns of the matrix in EACH processor MUST be the same.
10795 
10796 .seealso: [](chapter_matrices), `Mat`
10797 @*/
10798 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10799 {
10800   PetscMPIInt size;
10801 
10802   PetscFunctionBegin;
10803   PetscCallMPI(MPI_Comm_size(comm, &size));
10804   if (size == 1) {
10805     if (reuse == MAT_INITIAL_MATRIX) {
10806       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10807     } else {
10808       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10809     }
10810     PetscFunctionReturn(PETSC_SUCCESS);
10811   }
10812 
10813   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");
10814 
10815   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10816   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10817   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10818   PetscFunctionReturn(PETSC_SUCCESS);
10819 }
10820 
10821 /*@
10822      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10823 
10824     Collective
10825 
10826    Input Parameters:
10827 +    A   - the matrix to create subdomains from
10828 -    N   - requested number of subdomains
10829 
10830    Output Parameters:
10831 +    n   - number of subdomains resulting on this rank
10832 -    iss - `IS` list with indices of subdomains on this rank
10833 
10834     Level: advanced
10835 
10836     Note:
10837     The number of subdomains must be smaller than the communicator size
10838 
10839 .seealso: [](chapter_matrices), `Mat`, `IS`
10840 @*/
10841 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10842 {
10843   MPI_Comm    comm, subcomm;
10844   PetscMPIInt size, rank, color;
10845   PetscInt    rstart, rend, k;
10846 
10847   PetscFunctionBegin;
10848   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10849   PetscCallMPI(MPI_Comm_size(comm, &size));
10850   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10851   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);
10852   *n    = 1;
10853   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10854   color = rank / k;
10855   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10856   PetscCall(PetscMalloc1(1, iss));
10857   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10858   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10859   PetscCallMPI(MPI_Comm_free(&subcomm));
10860   PetscFunctionReturn(PETSC_SUCCESS);
10861 }
10862 
10863 /*@
10864    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10865 
10866    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10867    If they are not the same, uses `MatMatMatMult()`.
10868 
10869    Once the coarse grid problem is constructed, correct for interpolation operators
10870    that are not of full rank, which can legitimately happen in the case of non-nested
10871    geometric multigrid.
10872 
10873    Input Parameters:
10874 +  restrct - restriction operator
10875 .  dA - fine grid matrix
10876 .  interpolate - interpolation operator
10877 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10878 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10879 
10880    Output Parameter:
10881 .  A - the Galerkin coarse matrix
10882 
10883    Options Database Key:
10884 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10885 
10886    Level: developer
10887 
10888 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10889 @*/
10890 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10891 {
10892   IS  zerorows;
10893   Vec diag;
10894 
10895   PetscFunctionBegin;
10896   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10897   /* Construct the coarse grid matrix */
10898   if (interpolate == restrct) {
10899     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10900   } else {
10901     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10902   }
10903 
10904   /* If the interpolation matrix is not of full rank, A will have zero rows.
10905      This can legitimately happen in the case of non-nested geometric multigrid.
10906      In that event, we set the rows of the matrix to the rows of the identity,
10907      ignoring the equations (as the RHS will also be zero). */
10908 
10909   PetscCall(MatFindZeroRows(*A, &zerorows));
10910 
10911   if (zerorows != NULL) { /* if there are any zero rows */
10912     PetscCall(MatCreateVecs(*A, &diag, NULL));
10913     PetscCall(MatGetDiagonal(*A, diag));
10914     PetscCall(VecISSet(diag, zerorows, 1.0));
10915     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10916     PetscCall(VecDestroy(&diag));
10917     PetscCall(ISDestroy(&zerorows));
10918   }
10919   PetscFunctionReturn(PETSC_SUCCESS);
10920 }
10921 
10922 /*@C
10923     MatSetOperation - Allows user to set a matrix operation for any matrix type
10924 
10925    Logically Collective
10926 
10927     Input Parameters:
10928 +   mat - the matrix
10929 .   op - the name of the operation
10930 -   f - the function that provides the operation
10931 
10932    Level: developer
10933 
10934     Usage:
10935 .vb
10936   extern PetscErrorCode usermult(Mat, Vec, Vec);
10937 
10938   PetscCall(MatCreateXXX(comm, ..., &A));
10939   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10940 .ve
10941 
10942     Notes:
10943     See the file `include/petscmat.h` for a complete list of matrix
10944     operations, which all have the form MATOP_<OPERATION>, where
10945     <OPERATION> is the name (in all capital letters) of the
10946     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10947 
10948     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10949     sequence as the usual matrix interface routines, since they
10950     are intended to be accessed via the usual matrix interface
10951     routines, e.g.,
10952 .vb
10953   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10954 .ve
10955 
10956     In particular each function MUST return `PETSC_SUCCESS` on success and
10957     nonzero on failure.
10958 
10959     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10960 
10961 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10962 @*/
10963 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10964 {
10965   PetscFunctionBegin;
10966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10967   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10968   (((void (**)(void))mat->ops)[op]) = f;
10969   PetscFunctionReturn(PETSC_SUCCESS);
10970 }
10971 
10972 /*@C
10973     MatGetOperation - Gets a matrix operation for any matrix type.
10974 
10975     Not Collective
10976 
10977     Input Parameters:
10978 +   mat - the matrix
10979 -   op - the name of the operation
10980 
10981     Output Parameter:
10982 .   f - the function that provides the operation
10983 
10984     Level: developer
10985 
10986     Usage:
10987 .vb
10988       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10989       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10990 .ve
10991 
10992     Notes:
10993     See the file include/petscmat.h for a complete list of matrix
10994     operations, which all have the form MATOP_<OPERATION>, where
10995     <OPERATION> is the name (in all capital letters) of the
10996     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10997 
10998     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10999 
11000 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11001 @*/
11002 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11003 {
11004   PetscFunctionBegin;
11005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11006   *f = (((void (**)(void))mat->ops)[op]);
11007   PetscFunctionReturn(PETSC_SUCCESS);
11008 }
11009 
11010 /*@
11011     MatHasOperation - Determines whether the given matrix supports the particular operation.
11012 
11013    Not Collective
11014 
11015    Input Parameters:
11016 +  mat - the matrix
11017 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11018 
11019    Output Parameter:
11020 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11021 
11022    Level: advanced
11023 
11024    Note:
11025    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11026 
11027 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11028 @*/
11029 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11030 {
11031   PetscFunctionBegin;
11032   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11033   PetscValidBoolPointer(has, 3);
11034   if (mat->ops->hasoperation) {
11035     PetscUseTypeMethod(mat, hasoperation, op, has);
11036   } else {
11037     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11038     else {
11039       *has = PETSC_FALSE;
11040       if (op == MATOP_CREATE_SUBMATRIX) {
11041         PetscMPIInt size;
11042 
11043         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11044         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11045       }
11046     }
11047   }
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@
11052     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11053 
11054    Collective
11055 
11056    Input Parameter:
11057 .  mat - the matrix
11058 
11059    Output Parameter:
11060 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11061 
11062    Level: beginner
11063 
11064 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11065 @*/
11066 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11067 {
11068   PetscFunctionBegin;
11069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11070   PetscValidType(mat, 1);
11071   PetscValidBoolPointer(cong, 2);
11072   if (!mat->rmap || !mat->cmap) {
11073     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11074     PetscFunctionReturn(PETSC_SUCCESS);
11075   }
11076   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11077     PetscCall(PetscLayoutSetUp(mat->rmap));
11078     PetscCall(PetscLayoutSetUp(mat->cmap));
11079     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11080     if (*cong) mat->congruentlayouts = 1;
11081     else mat->congruentlayouts = 0;
11082   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11083   PetscFunctionReturn(PETSC_SUCCESS);
11084 }
11085 
11086 PetscErrorCode MatSetInf(Mat A)
11087 {
11088   PetscFunctionBegin;
11089   PetscUseTypeMethod(A, setinf);
11090   PetscFunctionReturn(PETSC_SUCCESS);
11091 }
11092 
11093 /*@C
11094    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
11095    and possibly removes small values from the graph structure.
11096 
11097    Collective
11098 
11099    Input Parameters:
11100 +  A - the matrix
11101 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11102 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11103 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11104 
11105    Output Parameter:
11106 .  graph - the resulting graph
11107 
11108    Level: advanced
11109 
11110 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11111 @*/
11112 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11113 {
11114   PetscFunctionBegin;
11115   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11116   PetscValidType(A, 1);
11117   PetscValidLogicalCollectiveBool(A, scale, 3);
11118   PetscValidPointer(graph, 5);
11119   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11120   PetscFunctionReturn(PETSC_SUCCESS);
11121 }
11122 
11123 /*@
11124   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11125   meaning the same memory is used for the matrix, and no new memory is allocated.
11126 
11127   Collective
11128 
11129   Input Parameter:
11130 . A - the matrix
11131 
11132   Level: intermediate
11133 
11134   Developer Note:
11135   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11136   of the arrays in the data structure are unneeded.
11137 
11138 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11139 @*/
11140 PetscErrorCode MatEliminateZeros(Mat A)
11141 {
11142   PetscFunctionBegin;
11143   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11144   PetscUseTypeMethod(A, eliminatezeros);
11145   PetscFunctionReturn(PETSC_SUCCESS);
11146 }
11147