xref: /petsc/src/mat/interface/matrix.c (revision 1d27aa22b2f6148b2c4e3f06a75e0638d6493e09)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
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   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(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: [](ch_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   PetscAssertPointer(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: [](ch_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 . mat - 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: [](ch_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   PetscAssertPointer(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 . mat - 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: [](ch_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   PetscAssertPointer(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: [](ch_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   PetscAssertPointer(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: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(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: [](ch_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 matrix 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()` or `VecCreateGhostBlock()`
427 
428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
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: [](ch_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) in the nonzero structure
471 
472   Not Collective
473 
474   Input Parameter:
475 . mat - the matrix
476 
477   Output Parameters:
478 + missing - is any diagonal entry missing
479 - dd      - first diagonal entry that is missing (optional) on this process
480 
481   Level: advanced
482 
483   Note:
484   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
485 
486 .seealso: [](ch_matrices), `Mat`
487 @*/
488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
489 {
490   PetscFunctionBegin;
491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
492   PetscValidType(mat, 1);
493   PetscAssertPointer(missing, 2);
494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
496   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
497   PetscFunctionReturn(PETSC_SUCCESS);
498 }
499 
500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
501 /*@C
502   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
503   for each row that you get to ensure that your application does
504   not bleed memory.
505 
506   Not Collective
507 
508   Input Parameters:
509 + mat - the matrix
510 - row - the row to get
511 
512   Output Parameters:
513 + ncols - if not `NULL`, the number of nonzeros in `row`
514 . cols  - if not `NULL`, the column numbers
515 - vals  - if not `NULL`, the numerical values
516 
517   Level: advanced
518 
519   Notes:
520   This routine is provided for people who need to have direct access
521   to the structure of a matrix.  We hope that we provide enough
522   high-level matrix routines that few users will need it.
523 
524   `MatGetRow()` always returns 0-based column indices, regardless of
525   whether the internal representation is 0-based (default) or 1-based.
526 
527   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
528   not wish to extract these quantities.
529 
530   The user can only examine the values extracted with `MatGetRow()`;
531   the values CANNOT be altered.  To change the matrix entries, one
532   must use `MatSetValues()`.
533 
534   You can only have one call to `MatGetRow()` outstanding for a particular
535   matrix at a time, per processor. `MatGetRow()` can only obtain rows
536   associated with the given processor, it cannot get rows from the
537   other processors; for that we suggest using `MatCreateSubMatrices()`, then
538   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
539   is in the global number of rows.
540 
541   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
542 
543   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
544 
545   Fortran Note:
546   The calling sequence is
547 .vb
548    MatGetRow(matrix,row,ncols,cols,values,ierr)
549          Mat     matrix (input)
550          integer row    (input)
551          integer ncols  (output)
552          integer cols(maxcols) (output)
553          double precision (or double complex) values(maxcols) output
554 .ve
555   where maxcols >= maximum nonzeros in any row of the matrix.
556 
557 .seealso: [](ch_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: [](ch_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: [](ch_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) PetscAssertPointer(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: [](ch_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: [](ch_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: [](ch_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: [](ch_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     PetscAssertPointer(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: [](ch_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: [](ch_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: [](ch_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   PetscAssertPointer(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 the user.
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: [](ch_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   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
900   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
901   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
902   PetscFunctionReturn(PETSC_SUCCESS);
903 }
904 
905 /*@
906   MatSetUp - Sets up the internal matrix data structures for later use.
907 
908   Collective
909 
910   Input Parameter:
911 . A - the matrix
912 
913   Level: intermediate
914 
915   Notes:
916   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
917   setting values in the matrix.
918 
919   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](ch_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 /*
945    If threadsafety is on extraneous matrices may be printed
946 
947    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
948 */
949 #if !defined(PETSC_HAVE_THREADSAFETY)
950 static PetscInt insidematview = 0;
951 #endif
952 
953 /*@C
954   MatViewFromOptions - View properties of the matrix based on options set in the options database
955 
956   Collective
957 
958   Input Parameters:
959 + A    - the matrix
960 . obj  - optional additional object that provides the options prefix to use
961 - name - command line option
962 
963   Options Database Key:
964 . -mat_view [viewertype]:... - the viewer and its options
965 
966   Level: intermediate
967 
968   Note:
969 .vb
970     If no value is provided ascii:stdout is used
971        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
972                                                   for example ascii::ascii_info prints just the information about the object not all details
973                                                   unless :append is given filename opens in write mode, overwriting what was already there
974        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
975        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
976        socket[:port]                             defaults to the standard output port
977        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
978 .ve
979 
980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
981 @*/
982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
983 {
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
986 #if !defined(PETSC_HAVE_THREADSAFETY)
987   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
988 #endif
989   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
990   PetscFunctionReturn(PETSC_SUCCESS);
991 }
992 
993 /*@C
994   MatView - display information about a matrix in a variety ways
995 
996   Collective
997 
998   Input Parameters:
999 + mat    - the matrix
1000 - viewer - visualization context
1001 
1002   Options Database Keys:
1003 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1004 . -mat_view ::ascii_info_detail    - Prints more detailed info
1005 . -mat_view                        - Prints matrix in ASCII format
1006 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1007 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1008 . -display <name>                  - Sets display name (default is host)
1009 . -draw_pause <sec>                - Sets number of seconds to pause after display
1010 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1011 . -viewer_socket_machine <machine> - -
1012 . -viewer_socket_port <port>       - -
1013 . -mat_view binary                 - save matrix to file in binary format
1014 - -viewer_binary_filename <name>   - -
1015 
1016   Level: beginner
1017 
1018   Notes:
1019   The available visualization contexts include
1020 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1021 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1022 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1023 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1024 
1025   The user can open alternative visualization contexts with
1026 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1027 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1028   specified file; corresponding input uses `MatLoad()`
1029 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1030   an X window display
1031 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1032   Currently only the `MATSEQDENSE` and `MATAIJ`
1033   matrix types support the Socket viewer.
1034 
1035   The user can call `PetscViewerPushFormat()` to specify the output
1036   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1037   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1038 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1039 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1040 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1041 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1042   format common among all matrix types
1043 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1044   format (which is in many cases the same as the default)
1045 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1046   size and structure (not the matrix entries)
1047 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1048   the matrix structure
1049 
1050   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1051   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1052 
1053   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1054 
1055   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1056   viewer is used.
1057 
1058   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1059   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1060 
1061   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1062   and then use the following mouse functions.
1063 .vb
1064   left mouse: zoom in
1065   middle mouse: zoom out
1066   right mouse: continue with the simulation
1067 .ve
1068 
1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1070           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1071 @*/
1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1073 {
1074   PetscInt          rows, cols, rbs, cbs;
1075   PetscBool         isascii, isstring, issaws;
1076   PetscViewerFormat format;
1077   PetscMPIInt       size;
1078 
1079   PetscFunctionBegin;
1080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1081   PetscValidType(mat, 1);
1082   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1083   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1084   PetscCheckSameComm(mat, 1, viewer, 2);
1085 
1086   PetscCall(PetscViewerGetFormat(viewer, &format));
1087   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1088   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1089 
1090 #if !defined(PETSC_HAVE_THREADSAFETY)
1091   insidematview++;
1092 #endif
1093   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1096   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");
1097 
1098   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1099   if (isascii) {
1100     if (!mat->preallocated) {
1101       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1102 #if !defined(PETSC_HAVE_THREADSAFETY)
1103       insidematview--;
1104 #endif
1105       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1106       PetscFunctionReturn(PETSC_SUCCESS);
1107     }
1108     if (!mat->assembled) {
1109       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1110 #if !defined(PETSC_HAVE_THREADSAFETY)
1111       insidematview--;
1112 #endif
1113       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1114       PetscFunctionReturn(PETSC_SUCCESS);
1115     }
1116     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1117     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1118       MatNullSpace nullsp, transnullsp;
1119 
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatGetSize(mat, &rows, &cols));
1122       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1123       if (rbs != 1 || cbs != 1) {
1124         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1125         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1126       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1127       if (mat->factortype) {
1128         MatSolverType solver;
1129         PetscCall(MatFactorGetSolverType(mat, &solver));
1130         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1131       }
1132       if (mat->ops->getinfo) {
1133         MatInfo info;
1134         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1135         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1136         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1137       }
1138       PetscCall(MatGetNullSpace(mat, &nullsp));
1139       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1140       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1141       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1142       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1144       PetscCall(PetscViewerASCIIPushTab(viewer));
1145       PetscCall(MatProductView(mat, viewer));
1146       PetscCall(PetscViewerASCIIPopTab(viewer));
1147     }
1148   } else if (issaws) {
1149 #if defined(PETSC_HAVE_SAWS)
1150     PetscMPIInt rank;
1151 
1152     PetscCall(PetscObjectName((PetscObject)mat));
1153     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1154     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1155 #endif
1156   } else if (isstring) {
1157     const char *type;
1158     PetscCall(MatGetType(mat, &type));
1159     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1160     PetscTryTypeMethod(mat, view, viewer);
1161   }
1162   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1163     PetscCall(PetscViewerASCIIPushTab(viewer));
1164     PetscUseTypeMethod(mat, viewnative, viewer);
1165     PetscCall(PetscViewerASCIIPopTab(viewer));
1166   } else if (mat->ops->view) {
1167     PetscCall(PetscViewerASCIIPushTab(viewer));
1168     PetscUseTypeMethod(mat, view, viewer);
1169     PetscCall(PetscViewerASCIIPopTab(viewer));
1170   }
1171   if (isascii) {
1172     PetscCall(PetscViewerGetFormat(viewer, &format));
1173     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1174   }
1175   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1176 #if !defined(PETSC_HAVE_THREADSAFETY)
1177   insidematview--;
1178 #endif
1179   PetscFunctionReturn(PETSC_SUCCESS);
1180 }
1181 
1182 #if defined(PETSC_USE_DEBUG)
1183   #include <../src/sys/totalview/tv_data_display.h>
1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1185 {
1186   TV_add_row("Local rows", "int", &mat->rmap->n);
1187   TV_add_row("Local columns", "int", &mat->cmap->n);
1188   TV_add_row("Global rows", "int", &mat->rmap->N);
1189   TV_add_row("Global columns", "int", &mat->cmap->N);
1190   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1191   return TV_format_OK;
1192 }
1193 #endif
1194 
1195 /*@C
1196   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1197   with `MatView()`.  The matrix format is determined from the options database.
1198   Generates a parallel MPI matrix if the communicator has more than one
1199   processor.  The default matrix type is `MATAIJ`.
1200 
1201   Collective
1202 
1203   Input Parameters:
1204 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1205             or some related function before a call to `MatLoad()`
1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1207 
1208   Options Database Key:
1209 . -matload_block_size <bs> - set block size
1210 
1211   Level: beginner
1212 
1213   Notes:
1214   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1215   `Mat` before calling this routine if you wish to set it from the options database.
1216 
1217   `MatLoad()` automatically loads into the options database any options
1218   given in the file filename.info where filename is the name of the file
1219   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1220   file will be ignored if you use the -viewer_binary_skip_info option.
1221 
1222   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1223   sets the default matrix type AIJ and sets the local and global sizes.
1224   If type and/or size is already set, then the same are used.
1225 
1226   In parallel, each processor can load a subset of rows (or the
1227   entire matrix).  This routine is especially useful when a large
1228   matrix is stored on disk and only part of it is desired on each
1229   processor.  For example, a parallel solver may access only some of
1230   the rows from each processor.  The algorithm used here reads
1231   relatively small blocks of data rather than reading the entire
1232   matrix and then subsetting it.
1233 
1234   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1235   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1236   or the sequence like
1237 .vb
1238     `PetscViewer` v;
1239     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1240     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1241     `PetscViewerSetFromOptions`(v);
1242     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1243     `PetscViewerFileSetName`(v,"datafile");
1244 .ve
1245   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1246 $ -viewer_type {binary, hdf5}
1247 
1248   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1249   and src/mat/tutorials/ex10.c with the second approach.
1250 
1251   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1252   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1253   Multiple objects, both matrices and vectors, can be stored within the same file.
1254   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1255 
1256   Most users should not need to know the details of the binary storage
1257   format, since `MatLoad()` and `MatView()` completely hide these details.
1258   But for anyone who is interested, the standard binary matrix storage
1259   format is
1260 
1261 .vb
1262     PetscInt    MAT_FILE_CLASSID
1263     PetscInt    number of rows
1264     PetscInt    number of columns
1265     PetscInt    total number of nonzeros
1266     PetscInt    *number nonzeros in each row
1267     PetscInt    *column indices of all nonzeros (starting index is zero)
1268     PetscScalar *values of all nonzeros
1269 .ve
1270   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1271   stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1272   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1273 
1274   PETSc automatically does the byte swapping for
1275   machines that store the bytes reversed. Thus if you write your own binary
1276   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1277   and `PetscBinaryWrite()` to see how this may be done.
1278 
1279   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1280   Each processor's chunk is loaded independently by its owning MPI process.
1281   Multiple objects, both matrices and vectors, can be stored within the same file.
1282   They are looked up by their PetscObject name.
1283 
1284   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1285   by default the same structure and naming of the AIJ arrays and column count
1286   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1287 $    save example.mat A b -v7.3
1288   can be directly read by this routine (see Reference 1 for details).
1289 
1290   Depending on your MATLAB version, this format might be a default,
1291   otherwise you can set it as default in Preferences.
1292 
1293   Unless -nocompression flag is used to save the file in MATLAB,
1294   PETSc must be configured with ZLIB package.
1295 
1296   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1297 
1298   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1299 
1300   Corresponding `MatView()` is not yet implemented.
1301 
1302   The loaded matrix is actually a transpose of the original one in MATLAB,
1303   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1304   With this format, matrix is automatically transposed by PETSc,
1305   unless the matrix is marked as SPD or symmetric
1306   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1307 
1308   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1309 
1310 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1311  @*/
1312 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1313 {
1314   PetscBool flg;
1315 
1316   PetscFunctionBegin;
1317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1318   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1319 
1320   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1321 
1322   flg = PETSC_FALSE;
1323   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1324   if (flg) {
1325     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1326     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1327   }
1328   flg = PETSC_FALSE;
1329   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1330   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1331 
1332   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1333   PetscUseTypeMethod(mat, load, viewer);
1334   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1339 {
1340   Mat_Redundant *redund = *redundant;
1341 
1342   PetscFunctionBegin;
1343   if (redund) {
1344     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1345       PetscCall(ISDestroy(&redund->isrow));
1346       PetscCall(ISDestroy(&redund->iscol));
1347       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1348     } else {
1349       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1350       PetscCall(PetscFree(redund->sbuf_j));
1351       PetscCall(PetscFree(redund->sbuf_a));
1352       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1353         PetscCall(PetscFree(redund->rbuf_j[i]));
1354         PetscCall(PetscFree(redund->rbuf_a[i]));
1355       }
1356       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1357     }
1358 
1359     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1360     PetscCall(PetscFree(redund));
1361   }
1362   PetscFunctionReturn(PETSC_SUCCESS);
1363 }
1364 
1365 /*@C
1366   MatDestroy - Frees space taken by a matrix.
1367 
1368   Collective
1369 
1370   Input Parameter:
1371 . A - the matrix
1372 
1373   Level: beginner
1374 
1375   Developer Note:
1376   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1377   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1378   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1379   if changes are needed here.
1380 
1381 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1382 @*/
1383 PetscErrorCode MatDestroy(Mat *A)
1384 {
1385   PetscFunctionBegin;
1386   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1387   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1388   if (--((PetscObject)(*A))->refct > 0) {
1389     *A = NULL;
1390     PetscFunctionReturn(PETSC_SUCCESS);
1391   }
1392 
1393   /* if memory was published with SAWs then destroy it */
1394   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1395   PetscTryTypeMethod((*A), destroy);
1396 
1397   PetscCall(PetscFree((*A)->factorprefix));
1398   PetscCall(PetscFree((*A)->defaultvectype));
1399   PetscCall(PetscFree((*A)->defaultrandtype));
1400   PetscCall(PetscFree((*A)->bsizes));
1401   PetscCall(PetscFree((*A)->solvertype));
1402   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1403   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1404   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1405   PetscCall(MatProductClear(*A));
1406   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1407   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1408   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1409   PetscCall(MatDestroy(&(*A)->schur));
1410   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1411   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1412   PetscCall(PetscHeaderDestroy(A));
1413   PetscFunctionReturn(PETSC_SUCCESS);
1414 }
1415 
1416 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1417 /*@C
1418   MatSetValues - Inserts or adds a block of values into a matrix.
1419   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1420   MUST be called after all calls to `MatSetValues()` have been completed.
1421 
1422   Not Collective
1423 
1424   Input Parameters:
1425 + mat  - the matrix
1426 . v    - a logically two-dimensional array of values
1427 . m    - the number of rows
1428 . idxm - the global indices of the rows
1429 . n    - the number of columns
1430 . idxn - the global indices of the columns
1431 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1432 
1433   Level: beginner
1434 
1435   Notes:
1436   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1437 
1438   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1439   options cannot be mixed without intervening calls to the assembly
1440   routines.
1441 
1442   `MatSetValues()` uses 0-based row and column numbers in Fortran
1443   as well as in C.
1444 
1445   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1446   simply ignored. This allows easily inserting element stiffness matrices
1447   with homogeneous Dirichlet boundary conditions that you don't want represented
1448   in the matrix.
1449 
1450   Efficiency Alert:
1451   The routine `MatSetValuesBlocked()` may offer much better efficiency
1452   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1453 
1454   Developer Note:
1455   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1456   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1457 
1458 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1459           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1460 @*/
1461 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1462 {
1463   PetscFunctionBeginHot;
1464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1465   PetscValidType(mat, 1);
1466   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1467   PetscAssertPointer(idxm, 3);
1468   PetscAssertPointer(idxn, 5);
1469   MatCheckPreallocated(mat, 1);
1470 
1471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1473 
1474   if (PetscDefined(USE_DEBUG)) {
1475     PetscInt i, j;
1476 
1477     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1478     for (i = 0; i < m; i++) {
1479       for (j = 0; j < n; j++) {
1480         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1481 #if defined(PETSC_USE_COMPLEX)
1482           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]);
1483 #else
1484           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]);
1485 #endif
1486       }
1487     }
1488     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);
1489     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);
1490   }
1491 
1492   if (mat->assembled) {
1493     mat->was_assembled = PETSC_TRUE;
1494     mat->assembled     = PETSC_FALSE;
1495   }
1496   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1497   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1498   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@C
1504   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . v    - a logically two-dimensional array of values
1513 . ism  - the rows to provide
1514 . isn  - the columns to provide
1515 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1516 
1517   Level: beginner
1518 
1519   Notes:
1520   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1521 
1522   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1523   options cannot be mixed without intervening calls to the assembly
1524   routines.
1525 
1526   `MatSetValues()` uses 0-based row and column numbers in Fortran
1527   as well as in C.
1528 
1529   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1530   simply ignored. This allows easily inserting element stiffness matrices
1531   with homogeneous Dirichlet boundary conditions that you don't want represented
1532   in the matrix.
1533 
1534   Efficiency Alert:
1535   The routine `MatSetValuesBlocked()` may offer much better efficiency
1536   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1537 
1538   This is currently not optimized for any particular `ISType`
1539 
1540   Developer Note:
1541   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1542   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1543 
1544 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1545           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1546 @*/
1547 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1548 {
1549   PetscInt        m, n;
1550   const PetscInt *rows, *cols;
1551 
1552   PetscFunctionBeginHot;
1553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1554   PetscCall(ISGetIndices(ism, &rows));
1555   PetscCall(ISGetIndices(isn, &cols));
1556   PetscCall(ISGetLocalSize(ism, &m));
1557   PetscCall(ISGetLocalSize(isn, &n));
1558   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1559   PetscCall(ISRestoreIndices(ism, &rows));
1560   PetscCall(ISRestoreIndices(isn, &cols));
1561   PetscFunctionReturn(PETSC_SUCCESS);
1562 }
1563 
1564 /*@
1565   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1566   values into a matrix
1567 
1568   Not Collective
1569 
1570   Input Parameters:
1571 + mat - the matrix
1572 . row - the (block) row to set
1573 - v   - a logically two-dimensional array of values
1574 
1575   Level: intermediate
1576 
1577   Notes:
1578   The values, `v`, are column-oriented (for the block version) and sorted
1579 
1580   All the nonzero values in `row` must be provided
1581 
1582   The matrix must have previously had its column indices set, likely by having been assembled.
1583 
1584   `row` must belong to this MPI process
1585 
1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1587           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1588 @*/
1589 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1590 {
1591   PetscInt globalrow;
1592 
1593   PetscFunctionBegin;
1594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1595   PetscValidType(mat, 1);
1596   PetscAssertPointer(v, 3);
1597   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1598   PetscCall(MatSetValuesRow(mat, globalrow, v));
1599   PetscFunctionReturn(PETSC_SUCCESS);
1600 }
1601 
1602 /*@
1603   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1604   values into a matrix
1605 
1606   Not Collective
1607 
1608   Input Parameters:
1609 + mat - the matrix
1610 . row - the (block) row to set
1611 - 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
1612 
1613   Level: advanced
1614 
1615   Notes:
1616   The values, `v`, are column-oriented for the block version.
1617 
1618   All the nonzeros in `row` must be provided
1619 
1620   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1621 
1622   `row` must belong to this process
1623 
1624 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1625           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1626 @*/
1627 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1628 {
1629   PetscFunctionBeginHot;
1630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1631   PetscValidType(mat, 1);
1632   MatCheckPreallocated(mat, 1);
1633   PetscAssertPointer(v, 3);
1634   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1635   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1636   mat->insertmode = INSERT_VALUES;
1637 
1638   if (mat->assembled) {
1639     mat->was_assembled = PETSC_TRUE;
1640     mat->assembled     = PETSC_FALSE;
1641   }
1642   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1643   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1644   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1645   PetscFunctionReturn(PETSC_SUCCESS);
1646 }
1647 
1648 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1649 /*@
1650   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1651   Using structured grid indexing
1652 
1653   Not Collective
1654 
1655   Input Parameters:
1656 + mat  - the matrix
1657 . m    - number of rows being entered
1658 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1659 . n    - number of columns being entered
1660 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1661 . v    - a logically two-dimensional array of values
1662 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1663 
1664   Level: beginner
1665 
1666   Notes:
1667   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1668 
1669   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1670   options cannot be mixed without intervening calls to the assembly
1671   routines.
1672 
1673   The grid coordinates are across the entire grid, not just the local portion
1674 
1675   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1676   as well as in C.
1677 
1678   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1679 
1680   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1681   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1682 
1683   The columns and rows in the stencil passed in MUST be contained within the
1684   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1685   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1686   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1687   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1688 
1689   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1690   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1691   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1692   `DM_BOUNDARY_PERIODIC` boundary type.
1693 
1694   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
1695   a single value per point) you can skip filling those indices.
1696 
1697   Inspired by the structured grid interface to the HYPRE package
1698   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1699 
1700   Efficiency Alert:
1701   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1702   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1703 
1704   Fortran Note:
1705   `idxm` and `idxn` should be declared as
1706 $     MatStencil idxm(4,m),idxn(4,n)
1707   and the values inserted using
1708 .vb
1709     idxm(MatStencil_i,1) = i
1710     idxm(MatStencil_j,1) = j
1711     idxm(MatStencil_k,1) = k
1712     idxm(MatStencil_c,1) = c
1713     etc
1714 .ve
1715 
1716 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1717           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1718 @*/
1719 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1720 {
1721   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1722   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1723   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1724 
1725   PetscFunctionBegin;
1726   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1728   PetscValidType(mat, 1);
1729   PetscAssertPointer(idxm, 3);
1730   PetscAssertPointer(idxn, 5);
1731 
1732   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1733     jdxm = buf;
1734     jdxn = buf + m;
1735   } else {
1736     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1737     jdxm = bufm;
1738     jdxn = bufn;
1739   }
1740   for (i = 0; i < m; i++) {
1741     for (j = 0; j < 3 - sdim; j++) dxm++;
1742     tmp = *dxm++ - starts[0];
1743     for (j = 0; j < dim - 1; j++) {
1744       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1745       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1746     }
1747     if (mat->stencil.noc) dxm++;
1748     jdxm[i] = tmp;
1749   }
1750   for (i = 0; i < n; i++) {
1751     for (j = 0; j < 3 - sdim; j++) dxn++;
1752     tmp = *dxn++ - starts[0];
1753     for (j = 0; j < dim - 1; j++) {
1754       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1755       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1756     }
1757     if (mat->stencil.noc) dxn++;
1758     jdxn[i] = tmp;
1759   }
1760   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1761   PetscCall(PetscFree2(bufm, bufn));
1762   PetscFunctionReturn(PETSC_SUCCESS);
1763 }
1764 
1765 /*@
1766   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1767   Using structured grid indexing
1768 
1769   Not Collective
1770 
1771   Input Parameters:
1772 + mat  - the matrix
1773 . m    - number of rows being entered
1774 . idxm - grid coordinates for matrix rows being entered
1775 . n    - number of columns being entered
1776 . idxn - grid coordinates for matrix columns being entered
1777 . v    - a logically two-dimensional array of values
1778 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1779 
1780   Level: beginner
1781 
1782   Notes:
1783   By default the values, `v`, are row-oriented and unsorted.
1784   See `MatSetOption()` for other options.
1785 
1786   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1787   options cannot be mixed without intervening calls to the assembly
1788   routines.
1789 
1790   The grid coordinates are across the entire grid, not just the local portion
1791 
1792   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1793   as well as in C.
1794 
1795   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1796 
1797   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1798   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1799 
1800   The columns and rows in the stencil passed in MUST be contained within the
1801   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1802   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1803   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1804   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1805 
1806   Negative indices may be passed in idxm and idxn, these rows and columns are
1807   simply ignored. This allows easily inserting element stiffness matrices
1808   with homogeneous Dirichlet boundary conditions that you don't want represented
1809   in the matrix.
1810 
1811   Inspired by the structured grid interface to the HYPRE package
1812   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1813 
1814   Fortran Note:
1815   `idxm` and `idxn` should be declared as
1816 $     MatStencil idxm(4,m),idxn(4,n)
1817   and the values inserted using
1818 .vb
1819     idxm(MatStencil_i,1) = i
1820     idxm(MatStencil_j,1) = j
1821     idxm(MatStencil_k,1) = k
1822    etc
1823 .ve
1824 
1825 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1826           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1827           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1828 @*/
1829 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1830 {
1831   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1832   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1833   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1834 
1835   PetscFunctionBegin;
1836   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1838   PetscValidType(mat, 1);
1839   PetscAssertPointer(idxm, 3);
1840   PetscAssertPointer(idxn, 5);
1841   PetscAssertPointer(v, 6);
1842 
1843   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1844     jdxm = buf;
1845     jdxn = buf + m;
1846   } else {
1847     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1848     jdxm = bufm;
1849     jdxn = bufn;
1850   }
1851   for (i = 0; i < m; i++) {
1852     for (j = 0; j < 3 - sdim; j++) dxm++;
1853     tmp = *dxm++ - starts[0];
1854     for (j = 0; j < sdim - 1; j++) {
1855       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1856       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1857     }
1858     dxm++;
1859     jdxm[i] = tmp;
1860   }
1861   for (i = 0; i < n; i++) {
1862     for (j = 0; j < 3 - sdim; j++) dxn++;
1863     tmp = *dxn++ - starts[0];
1864     for (j = 0; j < sdim - 1; j++) {
1865       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1866       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1867     }
1868     dxn++;
1869     jdxn[i] = tmp;
1870   }
1871   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1872   PetscCall(PetscFree2(bufm, bufn));
1873   PetscFunctionReturn(PETSC_SUCCESS);
1874 }
1875 
1876 /*@
1877   MatSetStencil - Sets the grid information for setting values into a matrix via
1878   `MatSetValuesStencil()`
1879 
1880   Not Collective
1881 
1882   Input Parameters:
1883 + mat    - the matrix
1884 . dim    - dimension of the grid 1, 2, or 3
1885 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1886 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1887 - dof    - number of degrees of freedom per node
1888 
1889   Level: beginner
1890 
1891   Notes:
1892   Inspired by the structured grid interface to the HYPRE package
1893   (www.llnl.gov/CASC/hyper)
1894 
1895   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1896   user.
1897 
1898 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1899           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1900 @*/
1901 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1902 {
1903   PetscFunctionBegin;
1904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1905   PetscAssertPointer(dims, 3);
1906   PetscAssertPointer(starts, 4);
1907 
1908   mat->stencil.dim = dim + (dof > 1);
1909   for (PetscInt i = 0; i < dim; i++) {
1910     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1911     mat->stencil.starts[i] = starts[dim - i - 1];
1912   }
1913   mat->stencil.dims[dim]   = dof;
1914   mat->stencil.starts[dim] = 0;
1915   mat->stencil.noc         = (PetscBool)(dof == 1);
1916   PetscFunctionReturn(PETSC_SUCCESS);
1917 }
1918 
1919 /*@C
1920   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1921 
1922   Not Collective
1923 
1924   Input Parameters:
1925 + mat  - the matrix
1926 . v    - a logically two-dimensional array of values
1927 . m    - the number of block rows
1928 . idxm - the global block indices
1929 . n    - the number of block columns
1930 . idxn - the global block indices
1931 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1932 
1933   Level: intermediate
1934 
1935   Notes:
1936   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1937   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1938 
1939   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1940   NOT the total number of rows/columns; for example, if the block size is 2 and
1941   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1942   The values in idxm would be 1 2; that is the first index for each block divided by
1943   the block size.
1944 
1945   You must call `MatSetBlockSize()` when constructing this matrix (before
1946   preallocating it).
1947 
1948   By default the values, `v`, are row-oriented, so the layout of
1949   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1950 
1951   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1952   options cannot be mixed without intervening calls to the assembly
1953   routines.
1954 
1955   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1956   as well as in C.
1957 
1958   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1959   simply ignored. This allows easily inserting element stiffness matrices
1960   with homogeneous Dirichlet boundary conditions that you don't want represented
1961   in the matrix.
1962 
1963   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1964   internal searching must be done to determine where to place the
1965   data in the matrix storage space.  By instead inserting blocks of
1966   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1967   reduced.
1968 
1969   Example:
1970 .vb
1971    Suppose m=n=2 and block size(bs) = 2 The array is
1972 
1973    1  2  | 3  4
1974    5  6  | 7  8
1975    - - - | - - -
1976    9  10 | 11 12
1977    13 14 | 15 16
1978 
1979    v[] should be passed in like
1980    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1981 
1982   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1983    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1984 .ve
1985 
1986 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1987 @*/
1988 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1989 {
1990   PetscFunctionBeginHot;
1991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1992   PetscValidType(mat, 1);
1993   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1994   PetscAssertPointer(idxm, 3);
1995   PetscAssertPointer(idxn, 5);
1996   MatCheckPreallocated(mat, 1);
1997   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1998   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1999   if (PetscDefined(USE_DEBUG)) {
2000     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2001     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2002   }
2003   if (PetscDefined(USE_DEBUG)) {
2004     PetscInt rbs, cbs, M, N, i;
2005     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2006     PetscCall(MatGetSize(mat, &M, &N));
2007     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);
2008     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);
2009   }
2010   if (mat->assembled) {
2011     mat->was_assembled = PETSC_TRUE;
2012     mat->assembled     = PETSC_FALSE;
2013   }
2014   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2015   if (mat->ops->setvaluesblocked) {
2016     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2017   } else {
2018     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2019     PetscInt i, j, bs, cbs;
2020 
2021     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2022     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2023       iidxm = buf;
2024       iidxn = buf + m * bs;
2025     } else {
2026       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2027       iidxm = bufr;
2028       iidxn = bufc;
2029     }
2030     for (i = 0; i < m; i++) {
2031       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2032     }
2033     if (m != n || bs != cbs || idxm != idxn) {
2034       for (i = 0; i < n; i++) {
2035         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2036       }
2037     } else iidxn = iidxm;
2038     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2039     PetscCall(PetscFree2(bufr, bufc));
2040   }
2041   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2042   PetscFunctionReturn(PETSC_SUCCESS);
2043 }
2044 
2045 /*@C
2046   MatGetValues - Gets a block of local values from a matrix.
2047 
2048   Not Collective; can only return values that are owned by the give process
2049 
2050   Input Parameters:
2051 + mat  - the matrix
2052 . v    - a logically two-dimensional array for storing the values
2053 . m    - the number of rows
2054 . idxm - the  global indices of the rows
2055 . n    - the number of columns
2056 - idxn - the global indices of the columns
2057 
2058   Level: advanced
2059 
2060   Notes:
2061   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2062   The values, `v`, are then returned in a row-oriented format,
2063   analogous to that used by default in `MatSetValues()`.
2064 
2065   `MatGetValues()` uses 0-based row and column numbers in
2066   Fortran as well as in C.
2067 
2068   `MatGetValues()` requires that the matrix has been assembled
2069   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2070   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2071   without intermediate matrix assembly.
2072 
2073   Negative row or column indices will be ignored and those locations in `v` will be
2074   left unchanged.
2075 
2076   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2077   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2078   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2079 
2080 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2081 @*/
2082 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2083 {
2084   PetscFunctionBegin;
2085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2086   PetscValidType(mat, 1);
2087   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2088   PetscAssertPointer(idxm, 3);
2089   PetscAssertPointer(idxn, 5);
2090   PetscAssertPointer(v, 6);
2091   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2092   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2093   MatCheckPreallocated(mat, 1);
2094 
2095   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2096   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2097   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2098   PetscFunctionReturn(PETSC_SUCCESS);
2099 }
2100 
2101 /*@C
2102   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2103   defined previously by `MatSetLocalToGlobalMapping()`
2104 
2105   Not Collective
2106 
2107   Input Parameters:
2108 + mat  - the matrix
2109 . nrow - number of rows
2110 . irow - the row local indices
2111 . ncol - number of columns
2112 - icol - the column local indices
2113 
2114   Output Parameter:
2115 . y - a logically two-dimensional array of values
2116 
2117   Level: advanced
2118 
2119   Notes:
2120   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2121 
2122   This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2123   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2124   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2125   with `MatSetLocalToGlobalMapping()`.
2126 
2127   Developer Note:
2128   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2129   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2130 
2131 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2132           `MatSetValuesLocal()`, `MatGetValues()`
2133 @*/
2134 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2135 {
2136   PetscFunctionBeginHot;
2137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2138   PetscValidType(mat, 1);
2139   MatCheckPreallocated(mat, 1);
2140   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2141   PetscAssertPointer(irow, 3);
2142   PetscAssertPointer(icol, 5);
2143   if (PetscDefined(USE_DEBUG)) {
2144     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2145     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2146   }
2147   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2148   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2149   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2150   else {
2151     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2152     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2153       irowm = buf;
2154       icolm = buf + nrow;
2155     } else {
2156       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2157       irowm = bufr;
2158       icolm = bufc;
2159     }
2160     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2161     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2163     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2164     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2165     PetscCall(PetscFree2(bufr, bufc));
2166   }
2167   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2168   PetscFunctionReturn(PETSC_SUCCESS);
2169 }
2170 
2171 /*@
2172   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2173   the same size. Currently, this can only be called once and creates the given matrix.
2174 
2175   Not Collective
2176 
2177   Input Parameters:
2178 + mat  - the matrix
2179 . nb   - the number of blocks
2180 . bs   - the number of rows (and columns) in each block
2181 . rows - a concatenation of the rows for each block
2182 - v    - a concatenation of logically two-dimensional arrays of values
2183 
2184   Level: advanced
2185 
2186   Notes:
2187   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2188 
2189   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2190 
2191 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2192           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2193 @*/
2194 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2195 {
2196   PetscFunctionBegin;
2197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2198   PetscValidType(mat, 1);
2199   PetscAssertPointer(rows, 4);
2200   PetscAssertPointer(v, 5);
2201   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2202 
2203   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2204   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2205   else {
2206     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2207   }
2208   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2209   PetscFunctionReturn(PETSC_SUCCESS);
2210 }
2211 
2212 /*@
2213   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2214   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2215   using a local (per-processor) numbering.
2216 
2217   Not Collective
2218 
2219   Input Parameters:
2220 + x        - the matrix
2221 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2222 - cmapping - column mapping
2223 
2224   Level: intermediate
2225 
2226   Note:
2227   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2228 
2229 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2230 @*/
2231 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2232 {
2233   PetscFunctionBegin;
2234   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2235   PetscValidType(x, 1);
2236   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2237   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2238   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2239   else {
2240     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2242   }
2243   PetscFunctionReturn(PETSC_SUCCESS);
2244 }
2245 
2246 /*@
2247   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2248 
2249   Not Collective
2250 
2251   Input Parameter:
2252 . A - the matrix
2253 
2254   Output Parameters:
2255 + rmapping - row mapping
2256 - cmapping - column mapping
2257 
2258   Level: advanced
2259 
2260 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2261 @*/
2262 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2263 {
2264   PetscFunctionBegin;
2265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2266   PetscValidType(A, 1);
2267   if (rmapping) {
2268     PetscAssertPointer(rmapping, 2);
2269     *rmapping = A->rmap->mapping;
2270   }
2271   if (cmapping) {
2272     PetscAssertPointer(cmapping, 3);
2273     *cmapping = A->cmap->mapping;
2274   }
2275   PetscFunctionReturn(PETSC_SUCCESS);
2276 }
2277 
2278 /*@
2279   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2280 
2281   Logically Collective
2282 
2283   Input Parameters:
2284 + A    - the matrix
2285 . rmap - row layout
2286 - cmap - column layout
2287 
2288   Level: advanced
2289 
2290   Note:
2291   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2292 
2293 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2294 @*/
2295 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2296 {
2297   PetscFunctionBegin;
2298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2299   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2300   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2301   PetscFunctionReturn(PETSC_SUCCESS);
2302 }
2303 
2304 /*@
2305   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2306 
2307   Not Collective
2308 
2309   Input Parameter:
2310 . A - the matrix
2311 
2312   Output Parameters:
2313 + rmap - row layout
2314 - cmap - column layout
2315 
2316   Level: advanced
2317 
2318 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2319 @*/
2320 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2321 {
2322   PetscFunctionBegin;
2323   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2324   PetscValidType(A, 1);
2325   if (rmap) {
2326     PetscAssertPointer(rmap, 2);
2327     *rmap = A->rmap;
2328   }
2329   if (cmap) {
2330     PetscAssertPointer(cmap, 3);
2331     *cmap = A->cmap;
2332   }
2333   PetscFunctionReturn(PETSC_SUCCESS);
2334 }
2335 
2336 /*@C
2337   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2338   using a local numbering of the rows and columns.
2339 
2340   Not Collective
2341 
2342   Input Parameters:
2343 + mat  - the matrix
2344 . nrow - number of rows
2345 . irow - the row local indices
2346 . ncol - number of columns
2347 . icol - the column local indices
2348 . y    - a logically two-dimensional array of values
2349 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2350 
2351   Level: intermediate
2352 
2353   Notes:
2354   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2355 
2356   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2357   options cannot be mixed without intervening calls to the assembly
2358   routines.
2359 
2360   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2361   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2362 
2363   Developer Note:
2364   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2365   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2366 
2367 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2368           `MatGetValuesLocal()`
2369 @*/
2370 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2371 {
2372   PetscFunctionBeginHot;
2373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2374   PetscValidType(mat, 1);
2375   MatCheckPreallocated(mat, 1);
2376   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2377   PetscAssertPointer(irow, 3);
2378   PetscAssertPointer(icol, 5);
2379   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2380   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2381   if (PetscDefined(USE_DEBUG)) {
2382     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2383     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2384   }
2385 
2386   if (mat->assembled) {
2387     mat->was_assembled = PETSC_TRUE;
2388     mat->assembled     = PETSC_FALSE;
2389   }
2390   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2391   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2392   else {
2393     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2394     const PetscInt *irowm, *icolm;
2395 
2396     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2397       bufr  = buf;
2398       bufc  = buf + nrow;
2399       irowm = bufr;
2400       icolm = bufc;
2401     } else {
2402       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2403       irowm = bufr;
2404       icolm = bufc;
2405     }
2406     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2407     else irowm = irow;
2408     if (mat->cmap->mapping) {
2409       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2410         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2411       } else icolm = irowm;
2412     } else icolm = icol;
2413     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2414     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2415   }
2416   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2417   PetscFunctionReturn(PETSC_SUCCESS);
2418 }
2419 
2420 /*@C
2421   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2422   using a local ordering of the nodes a block at a time.
2423 
2424   Not Collective
2425 
2426   Input Parameters:
2427 + mat  - the matrix
2428 . nrow - number of rows
2429 . irow - the row local indices
2430 . ncol - number of columns
2431 . icol - the column local indices
2432 . y    - a logically two-dimensional array of values
2433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2434 
2435   Level: intermediate
2436 
2437   Notes:
2438   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2439   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2440 
2441   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2442   options cannot be mixed without intervening calls to the assembly
2443   routines.
2444 
2445   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2446   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2447 
2448   Developer Note:
2449   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2450   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2451 
2452 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2453           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2454 @*/
2455 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2456 {
2457   PetscFunctionBeginHot;
2458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2459   PetscValidType(mat, 1);
2460   MatCheckPreallocated(mat, 1);
2461   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2462   PetscAssertPointer(irow, 3);
2463   PetscAssertPointer(icol, 5);
2464   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2465   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2466   if (PetscDefined(USE_DEBUG)) {
2467     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2468     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);
2469   }
2470 
2471   if (mat->assembled) {
2472     mat->was_assembled = PETSC_TRUE;
2473     mat->assembled     = PETSC_FALSE;
2474   }
2475   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2476     PetscInt irbs, rbs;
2477     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2478     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2479     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2480   }
2481   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2482     PetscInt icbs, cbs;
2483     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2484     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2485     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2486   }
2487   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2488   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2489   else {
2490     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2491     const PetscInt *irowm, *icolm;
2492 
2493     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2494       bufr  = buf;
2495       bufc  = buf + nrow;
2496       irowm = bufr;
2497       icolm = bufc;
2498     } else {
2499       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2500       irowm = bufr;
2501       icolm = bufc;
2502     }
2503     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2504     else irowm = irow;
2505     if (mat->cmap->mapping) {
2506       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2507         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2508       } else icolm = irowm;
2509     } else icolm = icol;
2510     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2511     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2512   }
2513   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2514   PetscFunctionReturn(PETSC_SUCCESS);
2515 }
2516 
2517 /*@
2518   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2519 
2520   Collective
2521 
2522   Input Parameters:
2523 + mat - the matrix
2524 - x   - the vector to be multiplied
2525 
2526   Output Parameter:
2527 . y - the result
2528 
2529   Level: developer
2530 
2531   Note:
2532   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2533   call `MatMultDiagonalBlock`(A,y,y).
2534 
2535 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2536 @*/
2537 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2538 {
2539   PetscFunctionBegin;
2540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2541   PetscValidType(mat, 1);
2542   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2543   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2544 
2545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2547   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2548   MatCheckPreallocated(mat, 1);
2549 
2550   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2551   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2552   PetscFunctionReturn(PETSC_SUCCESS);
2553 }
2554 
2555 /*@
2556   MatMult - Computes the matrix-vector product, $y = Ax$.
2557 
2558   Neighbor-wise Collective
2559 
2560   Input Parameters:
2561 + mat - the matrix
2562 - x   - the vector to be multiplied
2563 
2564   Output Parameter:
2565 . y - the result
2566 
2567   Level: beginner
2568 
2569   Note:
2570   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2571   call `MatMult`(A,y,y).
2572 
2573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2574 @*/
2575 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2576 {
2577   PetscFunctionBegin;
2578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2579   PetscValidType(mat, 1);
2580   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2581   VecCheckAssembled(x);
2582   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2583   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2584   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2585   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2586   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);
2587   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);
2588   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);
2589   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);
2590   PetscCall(VecSetErrorIfLocked(y, 3));
2591   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2592   MatCheckPreallocated(mat, 1);
2593 
2594   PetscCall(VecLockReadPush(x));
2595   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2596   PetscUseTypeMethod(mat, mult, x, y);
2597   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2599   PetscCall(VecLockReadPop(x));
2600   PetscFunctionReturn(PETSC_SUCCESS);
2601 }
2602 
2603 /*@
2604   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2605 
2606   Neighbor-wise Collective
2607 
2608   Input Parameters:
2609 + mat - the matrix
2610 - x   - the vector to be multiplied
2611 
2612   Output Parameter:
2613 . y - the result
2614 
2615   Level: beginner
2616 
2617   Notes:
2618   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2619   call `MatMultTranspose`(A,y,y).
2620 
2621   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2622   use `MatMultHermitianTranspose()`
2623 
2624 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2625 @*/
2626 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2627 {
2628   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2629 
2630   PetscFunctionBegin;
2631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2632   PetscValidType(mat, 1);
2633   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2634   VecCheckAssembled(x);
2635   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2636 
2637   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2639   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2640   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);
2641   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);
2642   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);
2643   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);
2644   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2645   MatCheckPreallocated(mat, 1);
2646 
2647   if (!mat->ops->multtranspose) {
2648     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2649     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);
2650   } else op = mat->ops->multtranspose;
2651   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2652   PetscCall(VecLockReadPush(x));
2653   PetscCall((*op)(mat, x, y));
2654   PetscCall(VecLockReadPop(x));
2655   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2658   PetscFunctionReturn(PETSC_SUCCESS);
2659 }
2660 
2661 /*@
2662   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2663 
2664   Neighbor-wise Collective
2665 
2666   Input Parameters:
2667 + mat - the matrix
2668 - x   - the vector to be multiplied
2669 
2670   Output Parameter:
2671 . y - the result
2672 
2673   Level: beginner
2674 
2675   Notes:
2676   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2677   call `MatMultHermitianTranspose`(A,y,y).
2678 
2679   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2680 
2681   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2682 
2683 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2684 @*/
2685 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2686 {
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2689   PetscValidType(mat, 1);
2690   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2691   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2692 
2693   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2695   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2696   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);
2697   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);
2698   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);
2699   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);
2700   MatCheckPreallocated(mat, 1);
2701 
2702   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2703 #if defined(PETSC_USE_COMPLEX)
2704   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2705     PetscCall(VecLockReadPush(x));
2706     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2707     else PetscUseTypeMethod(mat, mult, x, y);
2708     PetscCall(VecLockReadPop(x));
2709   } else {
2710     Vec w;
2711     PetscCall(VecDuplicate(x, &w));
2712     PetscCall(VecCopy(x, w));
2713     PetscCall(VecConjugate(w));
2714     PetscCall(MatMultTranspose(mat, w, y));
2715     PetscCall(VecDestroy(&w));
2716     PetscCall(VecConjugate(y));
2717   }
2718   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2719 #else
2720   PetscCall(MatMultTranspose(mat, x, y));
2721 #endif
2722   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2723   PetscFunctionReturn(PETSC_SUCCESS);
2724 }
2725 
2726 /*@
2727   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2728 
2729   Neighbor-wise Collective
2730 
2731   Input Parameters:
2732 + mat - the matrix
2733 . v1  - the vector to be multiplied by `mat`
2734 - v2  - the vector to be added to the result
2735 
2736   Output Parameter:
2737 . v3 - the result
2738 
2739   Level: beginner
2740 
2741   Note:
2742   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2743   call `MatMultAdd`(A,v1,v2,v1).
2744 
2745 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2746 @*/
2747 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2748 {
2749   PetscFunctionBegin;
2750   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2751   PetscValidType(mat, 1);
2752   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2753   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2754   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2755 
2756   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2757   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2758   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);
2759   /* 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);
2760      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); */
2761   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);
2762   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);
2763   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2764   MatCheckPreallocated(mat, 1);
2765 
2766   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2767   PetscCall(VecLockReadPush(v1));
2768   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2769   PetscCall(VecLockReadPop(v1));
2770   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2771   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2772   PetscFunctionReturn(PETSC_SUCCESS);
2773 }
2774 
2775 /*@
2776   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2777 
2778   Neighbor-wise Collective
2779 
2780   Input Parameters:
2781 + mat - the matrix
2782 . v1  - the vector to be multiplied by the transpose of the matrix
2783 - v2  - the vector to be added to the result
2784 
2785   Output Parameter:
2786 . v3 - the result
2787 
2788   Level: beginner
2789 
2790   Note:
2791   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2792   call `MatMultTransposeAdd`(A,v1,v2,v1).
2793 
2794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2795 @*/
2796 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2797 {
2798   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2799 
2800   PetscFunctionBegin;
2801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2802   PetscValidType(mat, 1);
2803   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2804   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2805   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2806 
2807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2808   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2809   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);
2810   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);
2811   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);
2812   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2813   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2814   MatCheckPreallocated(mat, 1);
2815 
2816   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2817   PetscCall(VecLockReadPush(v1));
2818   PetscCall((*op)(mat, v1, v2, v3));
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(PETSC_SUCCESS);
2823 }
2824 
2825 /*@
2826   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2827 
2828   Neighbor-wise Collective
2829 
2830   Input Parameters:
2831 + mat - the matrix
2832 . v1  - the vector to be multiplied by the Hermitian transpose
2833 - v2  - the vector to be added to the result
2834 
2835   Output Parameter:
2836 . v3 - the result
2837 
2838   Level: beginner
2839 
2840   Note:
2841   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2842   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2843 
2844 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2845 @*/
2846 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2847 {
2848   PetscFunctionBegin;
2849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2850   PetscValidType(mat, 1);
2851   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2852   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2853   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2854 
2855   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2856   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2857   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2858   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);
2859   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);
2860   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);
2861   MatCheckPreallocated(mat, 1);
2862 
2863   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2864   PetscCall(VecLockReadPush(v1));
2865   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2866   else {
2867     Vec w, z;
2868     PetscCall(VecDuplicate(v1, &w));
2869     PetscCall(VecCopy(v1, w));
2870     PetscCall(VecConjugate(w));
2871     PetscCall(VecDuplicate(v3, &z));
2872     PetscCall(MatMultTranspose(mat, w, z));
2873     PetscCall(VecDestroy(&w));
2874     PetscCall(VecConjugate(z));
2875     if (v2 != v3) {
2876       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2877     } else {
2878       PetscCall(VecAXPY(v3, 1.0, z));
2879     }
2880     PetscCall(VecDestroy(&z));
2881   }
2882   PetscCall(VecLockReadPop(v1));
2883   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2884   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2885   PetscFunctionReturn(PETSC_SUCCESS);
2886 }
2887 
2888 /*@C
2889   MatGetFactorType - gets the type of factorization a matrix is
2890 
2891   Not Collective
2892 
2893   Input Parameter:
2894 . mat - the matrix
2895 
2896   Output Parameter:
2897 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2898 
2899   Level: intermediate
2900 
2901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   PetscAssertPointer(t, 2);
2910   *t = mat->factortype;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915   MatSetFactorType - sets the type of factorization a matrix is
2916 
2917   Logically Collective
2918 
2919   Input Parameters:
2920 + mat - the matrix
2921 - 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`
2922 
2923   Level: intermediate
2924 
2925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2926           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2927 @*/
2928 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2929 {
2930   PetscFunctionBegin;
2931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2932   PetscValidType(mat, 1);
2933   mat->factortype = t;
2934   PetscFunctionReturn(PETSC_SUCCESS);
2935 }
2936 
2937 /*@C
2938   MatGetInfo - Returns information about matrix storage (number of
2939   nonzeros, memory, etc.).
2940 
2941   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2942 
2943   Input Parameters:
2944 + mat  - the matrix
2945 - 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)
2946 
2947   Output Parameter:
2948 . info - matrix information context
2949 
2950   Options Database Key:
2951 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2952 
2953   Notes:
2954   The `MatInfo` context contains a variety of matrix data, including
2955   number of nonzeros allocated and used, number of mallocs during
2956   matrix assembly, etc.  Additional information for factored matrices
2957   is provided (such as the fill ratio, number of mallocs during
2958   factorization, etc.).
2959 
2960   Example:
2961   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2962   data within the MatInfo context.  For example,
2963 .vb
2964       MatInfo info;
2965       Mat     A;
2966       double  mal, nz_a, nz_u;
2967 
2968       MatGetInfo(A, MAT_LOCAL, &info);
2969       mal  = info.mallocs;
2970       nz_a = info.nz_allocated;
2971 .ve
2972 
2973   Fortran users should declare info as a double precision
2974   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2975   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2976   a complete list of parameter names.
2977 .vb
2978       double  precision info(MAT_INFO_SIZE)
2979       double  precision mal, nz_a
2980       Mat     A
2981       integer ierr
2982 
2983       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2984       mal = info(MAT_INFO_MALLOCS)
2985       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2986 .ve
2987 
2988   Level: intermediate
2989 
2990   Developer Note:
2991   The Fortran interface is not autogenerated as the
2992   interface definition cannot be generated correctly [due to `MatInfo` argument]
2993 
2994 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2995 @*/
2996 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2997 {
2998   PetscFunctionBegin;
2999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3000   PetscValidType(mat, 1);
3001   PetscAssertPointer(info, 3);
3002   MatCheckPreallocated(mat, 1);
3003   PetscUseTypeMethod(mat, getinfo, flag, info);
3004   PetscFunctionReturn(PETSC_SUCCESS);
3005 }
3006 
3007 /*
3008    This is used by external packages where it is not easy to get the info from the actual
3009    matrix factorization.
3010 */
3011 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3012 {
3013   PetscFunctionBegin;
3014   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3015   PetscFunctionReturn(PETSC_SUCCESS);
3016 }
3017 
3018 /*@C
3019   MatLUFactor - Performs in-place LU factorization of matrix.
3020 
3021   Collective
3022 
3023   Input Parameters:
3024 + mat  - the matrix
3025 . row  - row permutation
3026 . col  - column permutation
3027 - info - options for factorization, includes
3028 .vb
3029           fill - expected fill as ratio of original fill.
3030           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3031                    Run with the option -info to determine an optimal value to use
3032 .ve
3033 
3034   Level: developer
3035 
3036   Notes:
3037   Most users should employ the `KSP` interface for linear solvers
3038   instead of working directly with matrix algebra routines such as this.
3039   See, e.g., `KSPCreate()`.
3040 
3041   This changes the state of the matrix to a factored matrix; it cannot be used
3042   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3043 
3044   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3045   when not using `KSP`.
3046 
3047   Developer Note:
3048   The Fortran interface is not autogenerated as the
3049   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3050 
3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3052           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3053 @*/
3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3055 {
3056   MatFactorInfo tinfo;
3057 
3058   PetscFunctionBegin;
3059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3062   if (info) PetscAssertPointer(info, 4);
3063   PetscValidType(mat, 1);
3064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3065   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3066   MatCheckPreallocated(mat, 1);
3067   if (!info) {
3068     PetscCall(MatFactorInfoInitialize(&tinfo));
3069     info = &tinfo;
3070   }
3071 
3072   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3073   PetscUseTypeMethod(mat, lufactor, row, col, info);
3074   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3075   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3076   PetscFunctionReturn(PETSC_SUCCESS);
3077 }
3078 
3079 /*@C
3080   MatILUFactor - Performs in-place ILU factorization of matrix.
3081 
3082   Collective
3083 
3084   Input Parameters:
3085 + mat  - the matrix
3086 . row  - row permutation
3087 . col  - column permutation
3088 - info - structure containing
3089 .vb
3090       levels - number of levels of fill.
3091       expected fill - as ratio of original fill.
3092       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3093                 missing diagonal entries)
3094 .ve
3095 
3096   Level: developer
3097 
3098   Notes:
3099   Most users should employ the `KSP` interface for linear solvers
3100   instead of working directly with matrix algebra routines such as this.
3101   See, e.g., `KSPCreate()`.
3102 
3103   Probably really in-place only when level of fill is zero, otherwise allocates
3104   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3105   when not using `KSP`.
3106 
3107   Developer Note:
3108   The Fortran interface is not autogenerated as the
3109   interface definition cannot be generated correctly [due to MatFactorInfo]
3110 
3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3112 @*/
3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3114 {
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3117   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3118   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3119   PetscAssertPointer(info, 4);
3120   PetscValidType(mat, 1);
3121   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3123   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3124   MatCheckPreallocated(mat, 1);
3125 
3126   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3127   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3128   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3129   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3130   PetscFunctionReturn(PETSC_SUCCESS);
3131 }
3132 
3133 /*@C
3134   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3135   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3136 
3137   Collective
3138 
3139   Input Parameters:
3140 + fact - the factor matrix obtained with `MatGetFactor()`
3141 . mat  - the matrix
3142 . row  - the row permutation
3143 . col  - the column permutation
3144 - info - options for factorization, includes
3145 .vb
3146           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3147           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3148 .ve
3149 
3150   Level: developer
3151 
3152   Notes:
3153   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3154 
3155   Most users should employ the simplified `KSP` interface for linear solvers
3156   instead of working directly with matrix algebra routines such as this.
3157   See, e.g., `KSPCreate()`.
3158 
3159   Developer Note:
3160   The Fortran interface is not autogenerated as the
3161   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3162 
3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3164 @*/
3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3166 {
3167   MatFactorInfo tinfo;
3168 
3169   PetscFunctionBegin;
3170   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3172   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3173   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3174   if (info) PetscAssertPointer(info, 5);
3175   PetscValidType(fact, 1);
3176   PetscValidType(mat, 2);
3177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3179   MatCheckPreallocated(mat, 2);
3180   if (!info) {
3181     PetscCall(MatFactorInfoInitialize(&tinfo));
3182     info = &tinfo;
3183   }
3184 
3185   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3186   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3189   PetscFunctionReturn(PETSC_SUCCESS);
3190 }
3191 
3192 /*@C
3193   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3194   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3195 
3196   Collective
3197 
3198   Input Parameters:
3199 + fact - the factor matrix obtained with `MatGetFactor()`
3200 . mat  - the matrix
3201 - info - options for factorization
3202 
3203   Level: developer
3204 
3205   Notes:
3206   See `MatLUFactor()` for in-place factorization.  See
3207   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3208 
3209   Most users should employ the `KSP` interface for linear solvers
3210   instead of working directly with matrix algebra routines such as this.
3211   See, e.g., `KSPCreate()`.
3212 
3213   Developer Note:
3214   The Fortran interface is not autogenerated as the
3215   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3216 
3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3218 @*/
3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3220 {
3221   MatFactorInfo tinfo;
3222 
3223   PetscFunctionBegin;
3224   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3226   PetscValidType(fact, 1);
3227   PetscValidType(mat, 2);
3228   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3229   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,
3230              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3231 
3232   MatCheckPreallocated(mat, 2);
3233   if (!info) {
3234     PetscCall(MatFactorInfoInitialize(&tinfo));
3235     info = &tinfo;
3236   }
3237 
3238   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3239   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3240   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3241   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3242   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3243   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3244   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3245   PetscFunctionReturn(PETSC_SUCCESS);
3246 }
3247 
3248 /*@C
3249   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3250   symmetric matrix.
3251 
3252   Collective
3253 
3254   Input Parameters:
3255 + mat  - the matrix
3256 . perm - row and column permutations
3257 - info - expected fill as ratio of original fill
3258 
3259   Level: developer
3260 
3261   Notes:
3262   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3263   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3264 
3265   Most users should employ the `KSP` interface for linear solvers
3266   instead of working directly with matrix algebra routines such as this.
3267   See, e.g., `KSPCreate()`.
3268 
3269   Developer Note:
3270   The Fortran interface is not autogenerated as the
3271   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3272 
3273 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3274           `MatGetOrdering()`
3275 @*/
3276 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3277 {
3278   MatFactorInfo tinfo;
3279 
3280   PetscFunctionBegin;
3281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3282   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3283   if (info) PetscAssertPointer(info, 3);
3284   PetscValidType(mat, 1);
3285   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3286   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3287   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3288   MatCheckPreallocated(mat, 1);
3289   if (!info) {
3290     PetscCall(MatFactorInfoInitialize(&tinfo));
3291     info = &tinfo;
3292   }
3293 
3294   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3295   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3296   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3297   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3298   PetscFunctionReturn(PETSC_SUCCESS);
3299 }
3300 
3301 /*@C
3302   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3303   of a symmetric matrix.
3304 
3305   Collective
3306 
3307   Input Parameters:
3308 + fact - the factor matrix obtained with `MatGetFactor()`
3309 . mat  - the matrix
3310 . perm - row and column permutations
3311 - info - options for factorization, includes
3312 .vb
3313           fill - expected fill as ratio of original fill.
3314           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3315                    Run with the option -info to determine an optimal value to use
3316 .ve
3317 
3318   Level: developer
3319 
3320   Notes:
3321   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3322   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3323 
3324   Most users should employ the `KSP` interface for linear solvers
3325   instead of working directly with matrix algebra routines such as this.
3326   See, e.g., `KSPCreate()`.
3327 
3328   Developer Note:
3329   The Fortran interface is not autogenerated as the
3330   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3331 
3332 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3333           `MatGetOrdering()`
3334 @*/
3335 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3336 {
3337   MatFactorInfo tinfo;
3338 
3339   PetscFunctionBegin;
3340   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3342   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3343   if (info) PetscAssertPointer(info, 4);
3344   PetscValidType(fact, 1);
3345   PetscValidType(mat, 2);
3346   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3347   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3348   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3349   MatCheckPreallocated(mat, 2);
3350   if (!info) {
3351     PetscCall(MatFactorInfoInitialize(&tinfo));
3352     info = &tinfo;
3353   }
3354 
3355   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3356   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3357   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3358   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3359   PetscFunctionReturn(PETSC_SUCCESS);
3360 }
3361 
3362 /*@C
3363   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3364   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3365   `MatCholeskyFactorSymbolic()`.
3366 
3367   Collective
3368 
3369   Input Parameters:
3370 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3371 . mat  - the initial matrix that is to be factored
3372 - info - options for factorization
3373 
3374   Level: developer
3375 
3376   Note:
3377   Most users should employ the `KSP` interface for linear solvers
3378   instead of working directly with matrix algebra routines such as this.
3379   See, e.g., `KSPCreate()`.
3380 
3381   Developer Note:
3382   The Fortran interface is not autogenerated as the
3383   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3384 
3385 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3386 @*/
3387 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3388 {
3389   MatFactorInfo tinfo;
3390 
3391   PetscFunctionBegin;
3392   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3394   PetscValidType(fact, 1);
3395   PetscValidType(mat, 2);
3396   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3397   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,
3398              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3399   MatCheckPreallocated(mat, 2);
3400   if (!info) {
3401     PetscCall(MatFactorInfoInitialize(&tinfo));
3402     info = &tinfo;
3403   }
3404 
3405   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3406   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3407   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3408   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3409   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3410   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3411   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3412   PetscFunctionReturn(PETSC_SUCCESS);
3413 }
3414 
3415 /*@
3416   MatQRFactor - Performs in-place QR factorization of matrix.
3417 
3418   Collective
3419 
3420   Input Parameters:
3421 + mat  - the matrix
3422 . col  - column permutation
3423 - info - options for factorization, includes
3424 .vb
3425           fill - expected fill as ratio of original fill.
3426           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3427                    Run with the option -info to determine an optimal value to use
3428 .ve
3429 
3430   Level: developer
3431 
3432   Notes:
3433   Most users should employ the `KSP` interface for linear solvers
3434   instead of working directly with matrix algebra routines such as this.
3435   See, e.g., `KSPCreate()`.
3436 
3437   This changes the state of the matrix to a factored matrix; it cannot be used
3438   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3439 
3440   Developer Note:
3441   The Fortran interface is not autogenerated as the
3442   interface definition cannot be generated correctly [due to MatFactorInfo]
3443 
3444 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3445           `MatSetUnfactored()`
3446 @*/
3447 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3448 {
3449   PetscFunctionBegin;
3450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3451   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3452   if (info) PetscAssertPointer(info, 3);
3453   PetscValidType(mat, 1);
3454   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3455   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3456   MatCheckPreallocated(mat, 1);
3457   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3458   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3459   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3460   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3461   PetscFunctionReturn(PETSC_SUCCESS);
3462 }
3463 
3464 /*@
3465   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3466   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3467 
3468   Collective
3469 
3470   Input Parameters:
3471 + fact - the factor matrix obtained with `MatGetFactor()`
3472 . mat  - the matrix
3473 . col  - column permutation
3474 - info - options for factorization, includes
3475 .vb
3476           fill - expected fill as ratio of original fill.
3477           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3478                    Run with the option -info to determine an optimal value to use
3479 .ve
3480 
3481   Level: developer
3482 
3483   Note:
3484   Most users should employ the `KSP` interface for linear solvers
3485   instead of working directly with matrix algebra routines such as this.
3486   See, e.g., `KSPCreate()`.
3487 
3488   Developer Note:
3489   The Fortran interface is not autogenerated as the
3490   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3491 
3492 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3493 @*/
3494 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3495 {
3496   MatFactorInfo tinfo;
3497 
3498   PetscFunctionBegin;
3499   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3501   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3502   if (info) PetscAssertPointer(info, 4);
3503   PetscValidType(fact, 1);
3504   PetscValidType(mat, 2);
3505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3507   MatCheckPreallocated(mat, 2);
3508   if (!info) {
3509     PetscCall(MatFactorInfoInitialize(&tinfo));
3510     info = &tinfo;
3511   }
3512 
3513   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3514   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3517   PetscFunctionReturn(PETSC_SUCCESS);
3518 }
3519 
3520 /*@
3521   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3522   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3523 
3524   Collective
3525 
3526   Input Parameters:
3527 + fact - the factor matrix obtained with `MatGetFactor()`
3528 . mat  - the matrix
3529 - info - options for factorization
3530 
3531   Level: developer
3532 
3533   Notes:
3534   See `MatQRFactor()` for in-place factorization.
3535 
3536   Most users should employ the `KSP` interface for linear solvers
3537   instead of working directly with matrix algebra routines such as this.
3538   See, e.g., `KSPCreate()`.
3539 
3540   Developer Note:
3541   The Fortran interface is not autogenerated as the
3542   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3543 
3544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3545 @*/
3546 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3547 {
3548   MatFactorInfo tinfo;
3549 
3550   PetscFunctionBegin;
3551   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3553   PetscValidType(fact, 1);
3554   PetscValidType(mat, 2);
3555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3556   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,
3557              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3558 
3559   MatCheckPreallocated(mat, 2);
3560   if (!info) {
3561     PetscCall(MatFactorInfoInitialize(&tinfo));
3562     info = &tinfo;
3563   }
3564 
3565   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3566   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3567   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3568   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3569   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3570   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3571   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3572   PetscFunctionReturn(PETSC_SUCCESS);
3573 }
3574 
3575 /*@
3576   MatSolve - Solves $A x = b$, given a factored matrix.
3577 
3578   Neighbor-wise Collective
3579 
3580   Input Parameters:
3581 + mat - the factored matrix
3582 - b   - the right-hand-side vector
3583 
3584   Output Parameter:
3585 . x - the result vector
3586 
3587   Level: developer
3588 
3589   Notes:
3590   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3591   call `MatSolve`(A,x,x).
3592 
3593   Most users should employ the `KSP` interface for linear solvers
3594   instead of working directly with matrix algebra routines such as this.
3595   See, e.g., `KSPCreate()`.
3596 
3597 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3598 @*/
3599 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3600 {
3601   PetscFunctionBegin;
3602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3603   PetscValidType(mat, 1);
3604   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3605   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3606   PetscCheckSameComm(mat, 1, b, 2);
3607   PetscCheckSameComm(mat, 1, x, 3);
3608   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3609   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);
3610   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);
3611   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);
3612   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3613   MatCheckPreallocated(mat, 1);
3614 
3615   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3616   if (mat->factorerrortype) {
3617     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3618     PetscCall(VecSetInf(x));
3619   } else PetscUseTypeMethod(mat, solve, b, x);
3620   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3621   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3622   PetscFunctionReturn(PETSC_SUCCESS);
3623 }
3624 
3625 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3626 {
3627   Vec      b, x;
3628   PetscInt N, i;
3629   PetscErrorCode (*f)(Mat, Vec, Vec);
3630   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3631 
3632   PetscFunctionBegin;
3633   if (A->factorerrortype) {
3634     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3635     PetscCall(MatSetInf(X));
3636     PetscFunctionReturn(PETSC_SUCCESS);
3637   }
3638   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3639   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3640   PetscCall(MatBoundToCPU(A, &Abound));
3641   if (!Abound) {
3642     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3643     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3644   }
3645 #if PetscDefined(HAVE_CUDA)
3646   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3647   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3648 #elif PetscDefined(HAVE_HIP)
3649   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3650   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3651 #endif
3652   PetscCall(MatGetSize(B, NULL, &N));
3653   for (i = 0; i < N; i++) {
3654     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3655     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3656     PetscCall((*f)(A, b, x));
3657     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3658     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3659   }
3660   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3661   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3662   PetscFunctionReturn(PETSC_SUCCESS);
3663 }
3664 
3665 /*@
3666   MatMatSolve - Solves $A X = B$, given a factored matrix.
3667 
3668   Neighbor-wise Collective
3669 
3670   Input Parameters:
3671 + A - the factored matrix
3672 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3673 
3674   Output Parameter:
3675 . X - the result matrix (dense matrix)
3676 
3677   Level: developer
3678 
3679   Note:
3680   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3681   otherwise, `B` and `X` cannot be the same.
3682 
3683 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3684 @*/
3685 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3686 {
3687   PetscFunctionBegin;
3688   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3689   PetscValidType(A, 1);
3690   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3691   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3692   PetscCheckSameComm(A, 1, B, 2);
3693   PetscCheckSameComm(A, 1, X, 3);
3694   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);
3695   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);
3696   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");
3697   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3698   MatCheckPreallocated(A, 1);
3699 
3700   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3701   if (!A->ops->matsolve) {
3702     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3703     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3704   } else PetscUseTypeMethod(A, matsolve, B, X);
3705   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3706   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3707   PetscFunctionReturn(PETSC_SUCCESS);
3708 }
3709 
3710 /*@
3711   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3712 
3713   Neighbor-wise Collective
3714 
3715   Input Parameters:
3716 + A - the factored matrix
3717 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3718 
3719   Output Parameter:
3720 . X - the result matrix (dense matrix)
3721 
3722   Level: developer
3723 
3724   Note:
3725   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3726   call `MatMatSolveTranspose`(A,X,X).
3727 
3728 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3729 @*/
3730 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3731 {
3732   PetscFunctionBegin;
3733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3734   PetscValidType(A, 1);
3735   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3736   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3737   PetscCheckSameComm(A, 1, B, 2);
3738   PetscCheckSameComm(A, 1, X, 3);
3739   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3740   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);
3741   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);
3742   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);
3743   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");
3744   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3745   MatCheckPreallocated(A, 1);
3746 
3747   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3748   if (!A->ops->matsolvetranspose) {
3749     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3750     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3751   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3752   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3753   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3754   PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756 
3757 /*@
3758   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3759 
3760   Neighbor-wise Collective
3761 
3762   Input Parameters:
3763 + A  - the factored matrix
3764 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3765 
3766   Output Parameter:
3767 . X - the result matrix (dense matrix)
3768 
3769   Level: developer
3770 
3771   Note:
3772   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create `Bt` in sparse compressed row
3773   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3774 
3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3776 @*/
3777 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3778 {
3779   PetscFunctionBegin;
3780   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3781   PetscValidType(A, 1);
3782   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3783   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3784   PetscCheckSameComm(A, 1, Bt, 2);
3785   PetscCheckSameComm(A, 1, X, 3);
3786 
3787   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3788   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);
3789   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);
3790   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");
3791   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3792   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3793   MatCheckPreallocated(A, 1);
3794 
3795   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3796   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3797   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3798   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3799   PetscFunctionReturn(PETSC_SUCCESS);
3800 }
3801 
3802 /*@
3803   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3804   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3805 
3806   Neighbor-wise Collective
3807 
3808   Input Parameters:
3809 + mat - the factored matrix
3810 - b   - the right-hand-side vector
3811 
3812   Output Parameter:
3813 . x - the result vector
3814 
3815   Level: developer
3816 
3817   Notes:
3818   `MatSolve()` should be used for most applications, as it performs
3819   a forward solve followed by a backward solve.
3820 
3821   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3822   call `MatForwardSolve`(A,x,x).
3823 
3824   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3825   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3826   `MatForwardSolve()` solves $U^T*D y = b$, and
3827   `MatBackwardSolve()` solves $U x = y$.
3828   Thus they do not provide a symmetric preconditioner.
3829 
3830 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3831 @*/
3832 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3833 {
3834   PetscFunctionBegin;
3835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3836   PetscValidType(mat, 1);
3837   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3838   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3839   PetscCheckSameComm(mat, 1, b, 2);
3840   PetscCheckSameComm(mat, 1, x, 3);
3841   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3842   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);
3843   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);
3844   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);
3845   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3846   MatCheckPreallocated(mat, 1);
3847 
3848   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3849   PetscUseTypeMethod(mat, forwardsolve, b, x);
3850   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3851   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3852   PetscFunctionReturn(PETSC_SUCCESS);
3853 }
3854 
3855 /*@
3856   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3857   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3858 
3859   Neighbor-wise Collective
3860 
3861   Input Parameters:
3862 + mat - the factored matrix
3863 - b   - the right-hand-side vector
3864 
3865   Output Parameter:
3866 . x - the result vector
3867 
3868   Level: developer
3869 
3870   Notes:
3871   `MatSolve()` should be used for most applications, as it performs
3872   a forward solve followed by a backward solve.
3873 
3874   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3875   call `MatBackwardSolve`(A,x,x).
3876 
3877   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3878   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3879   `MatForwardSolve()` solves $U^T*D y = b$, and
3880   `MatBackwardSolve()` solves $U x = y$.
3881   Thus they do not provide a symmetric preconditioner.
3882 
3883 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3884 @*/
3885 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3886 {
3887   PetscFunctionBegin;
3888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3889   PetscValidType(mat, 1);
3890   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3891   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3892   PetscCheckSameComm(mat, 1, b, 2);
3893   PetscCheckSameComm(mat, 1, x, 3);
3894   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3895   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);
3896   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);
3897   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);
3898   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3899   MatCheckPreallocated(mat, 1);
3900 
3901   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3902   PetscUseTypeMethod(mat, backwardsolve, b, x);
3903   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3904   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3905   PetscFunctionReturn(PETSC_SUCCESS);
3906 }
3907 
3908 /*@
3909   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3910 
3911   Neighbor-wise Collective
3912 
3913   Input Parameters:
3914 + mat - the factored matrix
3915 . b   - the right-hand-side vector
3916 - y   - the vector to be added to
3917 
3918   Output Parameter:
3919 . x - the result vector
3920 
3921   Level: developer
3922 
3923   Note:
3924   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3925   call `MatSolveAdd`(A,x,y,x).
3926 
3927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3928 @*/
3929 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3930 {
3931   PetscScalar one = 1.0;
3932   Vec         tmp;
3933 
3934   PetscFunctionBegin;
3935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3936   PetscValidType(mat, 1);
3937   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3938   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3939   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3940   PetscCheckSameComm(mat, 1, b, 2);
3941   PetscCheckSameComm(mat, 1, y, 3);
3942   PetscCheckSameComm(mat, 1, x, 4);
3943   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3944   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);
3945   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);
3946   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);
3947   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);
3948   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);
3949   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3950   MatCheckPreallocated(mat, 1);
3951 
3952   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3953   if (mat->factorerrortype) {
3954     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3955     PetscCall(VecSetInf(x));
3956   } else if (mat->ops->solveadd) {
3957     PetscUseTypeMethod(mat, solveadd, b, y, x);
3958   } else {
3959     /* do the solve then the add manually */
3960     if (x != y) {
3961       PetscCall(MatSolve(mat, b, x));
3962       PetscCall(VecAXPY(x, one, y));
3963     } else {
3964       PetscCall(VecDuplicate(x, &tmp));
3965       PetscCall(VecCopy(x, tmp));
3966       PetscCall(MatSolve(mat, b, x));
3967       PetscCall(VecAXPY(x, one, tmp));
3968       PetscCall(VecDestroy(&tmp));
3969     }
3970   }
3971   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3972   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3973   PetscFunctionReturn(PETSC_SUCCESS);
3974 }
3975 
3976 /*@
3977   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3978 
3979   Neighbor-wise Collective
3980 
3981   Input Parameters:
3982 + mat - the factored matrix
3983 - b   - the right-hand-side vector
3984 
3985   Output Parameter:
3986 . x - the result vector
3987 
3988   Level: developer
3989 
3990   Notes:
3991   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3992   call `MatSolveTranspose`(A,x,x).
3993 
3994   Most users should employ the `KSP` interface for linear solvers
3995   instead of working directly with matrix algebra routines such as this.
3996   See, e.g., `KSPCreate()`.
3997 
3998 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3999 @*/
4000 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4001 {
4002   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4003 
4004   PetscFunctionBegin;
4005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4006   PetscValidType(mat, 1);
4007   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4008   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4009   PetscCheckSameComm(mat, 1, b, 2);
4010   PetscCheckSameComm(mat, 1, x, 3);
4011   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4012   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);
4013   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);
4014   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4015   MatCheckPreallocated(mat, 1);
4016   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4017   if (mat->factorerrortype) {
4018     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4019     PetscCall(VecSetInf(x));
4020   } else {
4021     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4022     PetscCall((*f)(mat, b, x));
4023   }
4024   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4025   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4026   PetscFunctionReturn(PETSC_SUCCESS);
4027 }
4028 
4029 /*@
4030   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4031   factored matrix.
4032 
4033   Neighbor-wise Collective
4034 
4035   Input Parameters:
4036 + mat - the factored matrix
4037 . b   - the right-hand-side vector
4038 - y   - the vector to be added to
4039 
4040   Output Parameter:
4041 . x - the result vector
4042 
4043   Level: developer
4044 
4045   Note:
4046   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4047   call `MatSolveTransposeAdd`(A,x,y,x).
4048 
4049 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4050 @*/
4051 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4052 {
4053   PetscScalar one = 1.0;
4054   Vec         tmp;
4055   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4056 
4057   PetscFunctionBegin;
4058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4059   PetscValidType(mat, 1);
4060   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4061   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4062   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4063   PetscCheckSameComm(mat, 1, b, 2);
4064   PetscCheckSameComm(mat, 1, y, 3);
4065   PetscCheckSameComm(mat, 1, x, 4);
4066   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4067   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);
4068   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);
4069   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);
4070   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);
4071   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4072   MatCheckPreallocated(mat, 1);
4073 
4074   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4075   if (mat->factorerrortype) {
4076     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4077     PetscCall(VecSetInf(x));
4078   } else if (f) {
4079     PetscCall((*f)(mat, b, y, x));
4080   } else {
4081     /* do the solve then the add manually */
4082     if (x != y) {
4083       PetscCall(MatSolveTranspose(mat, b, x));
4084       PetscCall(VecAXPY(x, one, y));
4085     } else {
4086       PetscCall(VecDuplicate(x, &tmp));
4087       PetscCall(VecCopy(x, tmp));
4088       PetscCall(MatSolveTranspose(mat, b, x));
4089       PetscCall(VecAXPY(x, one, tmp));
4090       PetscCall(VecDestroy(&tmp));
4091     }
4092   }
4093   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4094   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4095   PetscFunctionReturn(PETSC_SUCCESS);
4096 }
4097 
4098 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4099 /*@
4100   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4101 
4102   Neighbor-wise Collective
4103 
4104   Input Parameters:
4105 + mat   - the matrix
4106 . b     - the right hand side
4107 . omega - the relaxation factor
4108 . flag  - flag indicating the type of SOR (see below)
4109 . shift - diagonal shift
4110 . its   - the number of iterations
4111 - lits  - the number of local iterations
4112 
4113   Output Parameter:
4114 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4115 
4116   SOR Flags:
4117 +     `SOR_FORWARD_SWEEP` - forward SOR
4118 .     `SOR_BACKWARD_SWEEP` - backward SOR
4119 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4120 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4121 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4122 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4123 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4124 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4125   upper/lower triangular part of matrix to
4126   vector (with omega)
4127 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4128 
4129   Level: developer
4130 
4131   Notes:
4132   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4133   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4134   on each processor.
4135 
4136   Application programmers will not generally use `MatSOR()` directly,
4137   but instead will employ the `KSP`/`PC` interface.
4138 
4139   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4140 
4141   Most users should employ the `KSP` interface for linear solvers
4142   instead of working directly with matrix algebra routines such as this.
4143   See, e.g., `KSPCreate()`.
4144 
4145   Vectors `x` and `b` CANNOT be the same
4146 
4147   The flags are implemented as bitwise inclusive or operations.
4148   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4149   to specify a zero initial guess for SSOR.
4150 
4151   Developer Note:
4152   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4153 
4154 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4155 @*/
4156 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4157 {
4158   PetscFunctionBegin;
4159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4160   PetscValidType(mat, 1);
4161   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4162   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4163   PetscCheckSameComm(mat, 1, b, 2);
4164   PetscCheckSameComm(mat, 1, x, 8);
4165   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4166   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4167   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);
4168   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);
4169   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);
4170   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4171   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4172   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4173 
4174   MatCheckPreallocated(mat, 1);
4175   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4176   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4177   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4178   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4179   PetscFunctionReturn(PETSC_SUCCESS);
4180 }
4181 
4182 /*
4183       Default matrix copy routine.
4184 */
4185 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4186 {
4187   PetscInt           i, rstart = 0, rend = 0, nz;
4188   const PetscInt    *cwork;
4189   const PetscScalar *vwork;
4190 
4191   PetscFunctionBegin;
4192   if (B->assembled) PetscCall(MatZeroEntries(B));
4193   if (str == SAME_NONZERO_PATTERN) {
4194     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4195     for (i = rstart; i < rend; i++) {
4196       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4197       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4198       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4199     }
4200   } else {
4201     PetscCall(MatAYPX(B, 0.0, A, str));
4202   }
4203   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4204   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4205   PetscFunctionReturn(PETSC_SUCCESS);
4206 }
4207 
4208 /*@
4209   MatCopy - Copies a matrix to another matrix.
4210 
4211   Collective
4212 
4213   Input Parameters:
4214 + A   - the matrix
4215 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4216 
4217   Output Parameter:
4218 . B - where the copy is put
4219 
4220   Level: intermediate
4221 
4222   Notes:
4223   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4224 
4225   `MatCopy()` copies the matrix entries of a matrix to another existing
4226   matrix (after first zeroing the second matrix).  A related routine is
4227   `MatConvert()`, which first creates a new matrix and then copies the data.
4228 
4229 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4230 @*/
4231 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4232 {
4233   PetscInt i;
4234 
4235   PetscFunctionBegin;
4236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4237   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4238   PetscValidType(A, 1);
4239   PetscValidType(B, 2);
4240   PetscCheckSameComm(A, 1, B, 2);
4241   MatCheckPreallocated(B, 2);
4242   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4243   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4244   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,
4245              A->cmap->N, B->cmap->N);
4246   MatCheckPreallocated(A, 1);
4247   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4248 
4249   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4250   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4251   else PetscCall(MatCopy_Basic(A, B, str));
4252 
4253   B->stencil.dim = A->stencil.dim;
4254   B->stencil.noc = A->stencil.noc;
4255   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4256     B->stencil.dims[i]   = A->stencil.dims[i];
4257     B->stencil.starts[i] = A->stencil.starts[i];
4258   }
4259 
4260   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4261   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4262   PetscFunctionReturn(PETSC_SUCCESS);
4263 }
4264 
4265 /*@C
4266   MatConvert - Converts a matrix to another matrix, either of the same
4267   or different type.
4268 
4269   Collective
4270 
4271   Input Parameters:
4272 + mat     - the matrix
4273 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4274    same type as the original matrix.
4275 - reuse   - denotes if the destination matrix is to be created or reused.
4276    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
4277    `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).
4278 
4279   Output Parameter:
4280 . M - pointer to place new matrix
4281 
4282   Level: intermediate
4283 
4284   Notes:
4285   `MatConvert()` first creates a new matrix and then copies the data from
4286   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4287   entries of one matrix to another already existing matrix context.
4288 
4289   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4290   the MPI communicator of the generated matrix is always the same as the communicator
4291   of the input matrix.
4292 
4293 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4294 @*/
4295 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4296 {
4297   PetscBool  sametype, issame, flg;
4298   PetscBool3 issymmetric, ishermitian;
4299   char       convname[256], mtype[256];
4300   Mat        B;
4301 
4302   PetscFunctionBegin;
4303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4304   PetscValidType(mat, 1);
4305   PetscAssertPointer(M, 4);
4306   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4307   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4308   MatCheckPreallocated(mat, 1);
4309 
4310   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4311   if (flg) newtype = mtype;
4312 
4313   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4314   PetscCall(PetscStrcmp(newtype, "same", &issame));
4315   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4316   if (reuse == MAT_REUSE_MATRIX) {
4317     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4318     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4319   }
4320 
4321   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4322     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4323     PetscFunctionReturn(PETSC_SUCCESS);
4324   }
4325 
4326   /* Cache Mat options because some converters use MatHeaderReplace  */
4327   issymmetric = mat->symmetric;
4328   ishermitian = mat->hermitian;
4329 
4330   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4331     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4332     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4333   } else {
4334     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4335     const char *prefix[3]                                 = {"seq", "mpi", ""};
4336     PetscInt    i;
4337     /*
4338        Order of precedence:
4339        0) See if newtype is a superclass of the current matrix.
4340        1) See if a specialized converter is known to the current matrix.
4341        2) See if a specialized converter is known to the desired matrix class.
4342        3) See if a good general converter is registered for the desired class
4343           (as of 6/27/03 only MATMPIADJ falls into this category).
4344        4) See if a good general converter is known for the current matrix.
4345        5) Use a really basic converter.
4346     */
4347 
4348     /* 0) See if newtype is a superclass of the current matrix.
4349           i.e mat is mpiaij and newtype is aij */
4350     for (i = 0; i < 2; i++) {
4351       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4353       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4354       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4355       if (flg) {
4356         if (reuse == MAT_INPLACE_MATRIX) {
4357           PetscCall(PetscInfo(mat, "Early return\n"));
4358           PetscFunctionReturn(PETSC_SUCCESS);
4359         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4360           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4361           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4364           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4365           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         }
4368       }
4369     }
4370     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4371     for (i = 0; i < 3; i++) {
4372       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4378       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4379       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4380       if (conv) goto foundconv;
4381     }
4382 
4383     /* 2)  See if a specialized converter is known to the desired matrix class. */
4384     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4385     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4386     PetscCall(MatSetType(B, newtype));
4387     for (i = 0; i < 3; i++) {
4388       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4394       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4395       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4396       if (conv) {
4397         PetscCall(MatDestroy(&B));
4398         goto foundconv;
4399       }
4400     }
4401 
4402     /* 3) See if a good general converter is registered for the desired class */
4403     conv = B->ops->convertfrom;
4404     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4405     PetscCall(MatDestroy(&B));
4406     if (conv) goto foundconv;
4407 
4408     /* 4) See if a good general converter is known for the current matrix */
4409     if (mat->ops->convert) conv = mat->ops->convert;
4410     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4411     if (conv) goto foundconv;
4412 
4413     /* 5) Use a really basic converter. */
4414     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4415     conv = MatConvert_Basic;
4416 
4417   foundconv:
4418     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4419     PetscCall((*conv)(mat, newtype, reuse, M));
4420     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4421       /* the block sizes must be same if the mappings are copied over */
4422       (*M)->rmap->bs = mat->rmap->bs;
4423       (*M)->cmap->bs = mat->cmap->bs;
4424       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4425       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4426       (*M)->rmap->mapping = mat->rmap->mapping;
4427       (*M)->cmap->mapping = mat->cmap->mapping;
4428     }
4429     (*M)->stencil.dim = mat->stencil.dim;
4430     (*M)->stencil.noc = mat->stencil.noc;
4431     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4432       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4433       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4434     }
4435     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4436   }
4437   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4438 
4439   /* Copy Mat options */
4440   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4441   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4442   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4443   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4444   PetscFunctionReturn(PETSC_SUCCESS);
4445 }
4446 
4447 /*@C
4448   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4449 
4450   Not Collective
4451 
4452   Input Parameter:
4453 . mat - the matrix, must be a factored matrix
4454 
4455   Output Parameter:
4456 . type - the string name of the package (do not free this string)
4457 
4458   Level: intermediate
4459 
4460   Fortran Note:
4461   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4462 
4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4464 @*/
4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4466 {
4467   PetscErrorCode (*conv)(Mat, MatSolverType *);
4468 
4469   PetscFunctionBegin;
4470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4471   PetscValidType(mat, 1);
4472   PetscAssertPointer(type, 2);
4473   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4474   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4475   if (conv) PetscCall((*conv)(mat, type));
4476   else *type = MATSOLVERPETSC;
4477   PetscFunctionReturn(PETSC_SUCCESS);
4478 }
4479 
4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4481 struct _MatSolverTypeForSpecifcType {
4482   MatType mtype;
4483   /* no entry for MAT_FACTOR_NONE */
4484   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4485   MatSolverTypeForSpecifcType next;
4486 };
4487 
4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4489 struct _MatSolverTypeHolder {
4490   char                       *name;
4491   MatSolverTypeForSpecifcType handlers;
4492   MatSolverTypeHolder         next;
4493 };
4494 
4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4496 
4497 /*@C
4498   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4499 
4500   Input Parameters:
4501 + package      - name of the package, for example petsc or superlu
4502 . mtype        - the matrix type that works with this package
4503 . ftype        - the type of factorization supported by the package
4504 - createfactor - routine that will create the factored matrix ready to be used
4505 
4506   Level: developer
4507 
4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4509 @*/
4510 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4511 {
4512   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4513   PetscBool                   flg;
4514   MatSolverTypeForSpecifcType inext, iprev = NULL;
4515 
4516   PetscFunctionBegin;
4517   PetscCall(MatInitializePackage());
4518   if (!next) {
4519     PetscCall(PetscNew(&MatSolverTypeHolders));
4520     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4521     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4522     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4523     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4524     PetscFunctionReturn(PETSC_SUCCESS);
4525   }
4526   while (next) {
4527     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4528     if (flg) {
4529       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4530       inext = next->handlers;
4531       while (inext) {
4532         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4533         if (flg) {
4534           inext->createfactor[(int)ftype - 1] = createfactor;
4535           PetscFunctionReturn(PETSC_SUCCESS);
4536         }
4537         iprev = inext;
4538         inext = inext->next;
4539       }
4540       PetscCall(PetscNew(&iprev->next));
4541       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4542       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4543       PetscFunctionReturn(PETSC_SUCCESS);
4544     }
4545     prev = next;
4546     next = next->next;
4547   }
4548   PetscCall(PetscNew(&prev->next));
4549   PetscCall(PetscStrallocpy(package, &prev->next->name));
4550   PetscCall(PetscNew(&prev->next->handlers));
4551   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4552   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4553   PetscFunctionReturn(PETSC_SUCCESS);
4554 }
4555 
4556 /*@C
4557   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4558 
4559   Input Parameters:
4560 + type  - name of the package, for example petsc or superlu
4561 . ftype - the type of factorization supported by the type
4562 - mtype - the matrix type that works with this type
4563 
4564   Output Parameters:
4565 + foundtype    - `PETSC_TRUE` if the type was registered
4566 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4567 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4568 
4569   Level: developer
4570 
4571 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4572 @*/
4573 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4574 {
4575   MatSolverTypeHolder         next = MatSolverTypeHolders;
4576   PetscBool                   flg;
4577   MatSolverTypeForSpecifcType inext;
4578 
4579   PetscFunctionBegin;
4580   if (foundtype) *foundtype = PETSC_FALSE;
4581   if (foundmtype) *foundmtype = PETSC_FALSE;
4582   if (createfactor) *createfactor = NULL;
4583 
4584   if (type) {
4585     while (next) {
4586       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4587       if (flg) {
4588         if (foundtype) *foundtype = PETSC_TRUE;
4589         inext = next->handlers;
4590         while (inext) {
4591           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4592           if (flg) {
4593             if (foundmtype) *foundmtype = PETSC_TRUE;
4594             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4595             PetscFunctionReturn(PETSC_SUCCESS);
4596           }
4597           inext = inext->next;
4598         }
4599       }
4600       next = next->next;
4601     }
4602   } else {
4603     while (next) {
4604       inext = next->handlers;
4605       while (inext) {
4606         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4607         if (flg && inext->createfactor[(int)ftype - 1]) {
4608           if (foundtype) *foundtype = PETSC_TRUE;
4609           if (foundmtype) *foundmtype = PETSC_TRUE;
4610           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4611           PetscFunctionReturn(PETSC_SUCCESS);
4612         }
4613         inext = inext->next;
4614       }
4615       next = next->next;
4616     }
4617     /* try with base classes inext->mtype */
4618     next = MatSolverTypeHolders;
4619     while (next) {
4620       inext = next->handlers;
4621       while (inext) {
4622         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4623         if (flg && inext->createfactor[(int)ftype - 1]) {
4624           if (foundtype) *foundtype = PETSC_TRUE;
4625           if (foundmtype) *foundmtype = PETSC_TRUE;
4626           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4627           PetscFunctionReturn(PETSC_SUCCESS);
4628         }
4629         inext = inext->next;
4630       }
4631       next = next->next;
4632     }
4633   }
4634   PetscFunctionReturn(PETSC_SUCCESS);
4635 }
4636 
4637 PetscErrorCode MatSolverTypeDestroy(void)
4638 {
4639   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4640   MatSolverTypeForSpecifcType inext, iprev;
4641 
4642   PetscFunctionBegin;
4643   while (next) {
4644     PetscCall(PetscFree(next->name));
4645     inext = next->handlers;
4646     while (inext) {
4647       PetscCall(PetscFree(inext->mtype));
4648       iprev = inext;
4649       inext = inext->next;
4650       PetscCall(PetscFree(iprev));
4651     }
4652     prev = next;
4653     next = next->next;
4654     PetscCall(PetscFree(prev));
4655   }
4656   MatSolverTypeHolders = NULL;
4657   PetscFunctionReturn(PETSC_SUCCESS);
4658 }
4659 
4660 /*@C
4661   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4662 
4663   Logically Collective
4664 
4665   Input Parameter:
4666 . mat - the matrix
4667 
4668   Output Parameter:
4669 . flg - `PETSC_TRUE` if uses the ordering
4670 
4671   Level: developer
4672 
4673   Note:
4674   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4675   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4676 
4677 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4678 @*/
4679 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4680 {
4681   PetscFunctionBegin;
4682   *flg = mat->canuseordering;
4683   PetscFunctionReturn(PETSC_SUCCESS);
4684 }
4685 
4686 /*@C
4687   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4688 
4689   Logically Collective
4690 
4691   Input Parameters:
4692 + mat   - the matrix obtained with `MatGetFactor()`
4693 - ftype - the factorization type to be used
4694 
4695   Output Parameter:
4696 . otype - the preferred ordering type
4697 
4698   Level: developer
4699 
4700 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4701 @*/
4702 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4703 {
4704   PetscFunctionBegin;
4705   *otype = mat->preferredordering[ftype];
4706   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4707   PetscFunctionReturn(PETSC_SUCCESS);
4708 }
4709 
4710 /*@C
4711   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4712 
4713   Collective
4714 
4715   Input Parameters:
4716 + mat   - the matrix
4717 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4718 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4719 
4720   Output Parameter:
4721 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4722 
4723   Options Database Key:
4724 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4725                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4726 
4727   Level: intermediate
4728 
4729   Notes:
4730   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4731   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4732 
4733   Users usually access the factorization solvers via `KSP`
4734 
4735   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4736   such as pastix, superlu, mumps etc.
4737 
4738   PETSc must have been ./configure to use the external solver, using the option --download-package
4739 
4740   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4741   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4742   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4743 
4744   Developer Note:
4745   This should actually be called `MatCreateFactor()` since it creates a new factor object
4746 
4747 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4748           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4749 @*/
4750 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4751 {
4752   PetscBool foundtype, foundmtype;
4753   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4754 
4755   PetscFunctionBegin;
4756   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4757   PetscValidType(mat, 1);
4758 
4759   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4760   MatCheckPreallocated(mat, 1);
4761 
4762   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4763   if (!foundtype) {
4764     if (type) {
4765       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],
4766               ((PetscObject)mat)->type_name, type);
4767     } else {
4768       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);
4769     }
4770   }
4771   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4772   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);
4773 
4774   PetscCall((*conv)(mat, ftype, f));
4775   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4776   PetscFunctionReturn(PETSC_SUCCESS);
4777 }
4778 
4779 /*@C
4780   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4781 
4782   Not Collective
4783 
4784   Input Parameters:
4785 + mat   - the matrix
4786 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4787 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4788 
4789   Output Parameter:
4790 . flg - PETSC_TRUE if the factorization is available
4791 
4792   Level: intermediate
4793 
4794   Notes:
4795   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4796   such as pastix, superlu, mumps etc.
4797 
4798   PETSc must have been ./configure to use the external solver, using the option --download-package
4799 
4800   Developer Note:
4801   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4802 
4803 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4804           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4805 @*/
4806 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4807 {
4808   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4809 
4810   PetscFunctionBegin;
4811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4812   PetscValidType(mat, 1);
4813   PetscAssertPointer(flg, 4);
4814 
4815   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4816   MatCheckPreallocated(mat, 1);
4817 
4818   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4819   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4820   PetscFunctionReturn(PETSC_SUCCESS);
4821 }
4822 
4823 /*@
4824   MatDuplicate - Duplicates a matrix including the non-zero structure.
4825 
4826   Collective
4827 
4828   Input Parameters:
4829 + mat - the matrix
4830 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4831         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4832 
4833   Output Parameter:
4834 . M - pointer to place new matrix
4835 
4836   Level: intermediate
4837 
4838   Notes:
4839   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4840 
4841   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4842 
4843   May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.
4844 
4845   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4846   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4847   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4848 
4849 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4850 @*/
4851 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4852 {
4853   Mat         B;
4854   VecType     vtype;
4855   PetscInt    i;
4856   PetscObject dm, container_h, container_d;
4857   void (*viewf)(void);
4858 
4859   PetscFunctionBegin;
4860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4861   PetscValidType(mat, 1);
4862   PetscAssertPointer(M, 3);
4863   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4864   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4865   MatCheckPreallocated(mat, 1);
4866 
4867   *M = NULL;
4868   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4869   PetscUseTypeMethod(mat, duplicate, op, M);
4870   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4871   B = *M;
4872 
4873   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4874   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4875   PetscCall(MatGetVecType(mat, &vtype));
4876   PetscCall(MatSetVecType(B, vtype));
4877 
4878   B->stencil.dim = mat->stencil.dim;
4879   B->stencil.noc = mat->stencil.noc;
4880   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4881     B->stencil.dims[i]   = mat->stencil.dims[i];
4882     B->stencil.starts[i] = mat->stencil.starts[i];
4883   }
4884 
4885   B->nooffproczerorows = mat->nooffproczerorows;
4886   B->nooffprocentries  = mat->nooffprocentries;
4887 
4888   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4889   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4890   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4891   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4892   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4893   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4894   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4895   PetscFunctionReturn(PETSC_SUCCESS);
4896 }
4897 
4898 /*@
4899   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4900 
4901   Logically Collective
4902 
4903   Input Parameter:
4904 . mat - the matrix
4905 
4906   Output Parameter:
4907 . v - the diagonal of the matrix
4908 
4909   Level: intermediate
4910 
4911   Note:
4912   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4913   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4914   is larger than `ndiag`, the values of the remaining entries are unspecified.
4915 
4916   Currently only correct in parallel for square matrices.
4917 
4918 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4919 @*/
4920 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4921 {
4922   PetscFunctionBegin;
4923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4924   PetscValidType(mat, 1);
4925   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4926   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4927   MatCheckPreallocated(mat, 1);
4928   if (PetscDefined(USE_DEBUG)) {
4929     PetscInt nv, row, col, ndiag;
4930 
4931     PetscCall(VecGetLocalSize(v, &nv));
4932     PetscCall(MatGetLocalSize(mat, &row, &col));
4933     ndiag = PetscMin(row, col);
4934     PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag);
4935   }
4936 
4937   PetscUseTypeMethod(mat, getdiagonal, v);
4938   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4939   PetscFunctionReturn(PETSC_SUCCESS);
4940 }
4941 
4942 /*@C
4943   MatGetRowMin - Gets the minimum value (of the real part) of each
4944   row of the matrix
4945 
4946   Logically Collective
4947 
4948   Input Parameter:
4949 . mat - the matrix
4950 
4951   Output Parameters:
4952 + v   - the vector for storing the maximums
4953 - idx - the indices of the column found for each row (optional)
4954 
4955   Level: intermediate
4956 
4957   Note:
4958   The result of this call are the same as if one converted the matrix to dense format
4959   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4960 
4961   This code is only implemented for a couple of matrix formats.
4962 
4963 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4964           `MatGetRowMax()`
4965 @*/
4966 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4967 {
4968   PetscFunctionBegin;
4969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4970   PetscValidType(mat, 1);
4971   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4972   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4973 
4974   if (!mat->cmap->N) {
4975     PetscCall(VecSet(v, PETSC_MAX_REAL));
4976     if (idx) {
4977       PetscInt i, m = mat->rmap->n;
4978       for (i = 0; i < m; i++) idx[i] = -1;
4979     }
4980   } else {
4981     MatCheckPreallocated(mat, 1);
4982   }
4983   PetscUseTypeMethod(mat, getrowmin, v, idx);
4984   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4985   PetscFunctionReturn(PETSC_SUCCESS);
4986 }
4987 
4988 /*@C
4989   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4990   row of the matrix
4991 
4992   Logically Collective
4993 
4994   Input Parameter:
4995 . mat - the matrix
4996 
4997   Output Parameters:
4998 + v   - the vector for storing the minimums
4999 - idx - the indices of the column found for each row (or `NULL` if not needed)
5000 
5001   Level: intermediate
5002 
5003   Notes:
5004   if a row is completely empty or has only 0.0 values then the `idx` value for that
5005   row is 0 (the first column).
5006 
5007   This code is only implemented for a couple of matrix formats.
5008 
5009 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5010 @*/
5011 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5012 {
5013   PetscFunctionBegin;
5014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5015   PetscValidType(mat, 1);
5016   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5017   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5018   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5019 
5020   if (!mat->cmap->N) {
5021     PetscCall(VecSet(v, 0.0));
5022     if (idx) {
5023       PetscInt i, m = mat->rmap->n;
5024       for (i = 0; i < m; i++) idx[i] = -1;
5025     }
5026   } else {
5027     MatCheckPreallocated(mat, 1);
5028     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5029     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5030   }
5031   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5032   PetscFunctionReturn(PETSC_SUCCESS);
5033 }
5034 
5035 /*@C
5036   MatGetRowMax - Gets the maximum value (of the real part) of each
5037   row of the matrix
5038 
5039   Logically Collective
5040 
5041   Input Parameter:
5042 . mat - the matrix
5043 
5044   Output Parameters:
5045 + v   - the vector for storing the maximums
5046 - idx - the indices of the column found for each row (optional)
5047 
5048   Level: intermediate
5049 
5050   Notes:
5051   The result of this call are the same as if one converted the matrix to dense format
5052   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5053 
5054   This code is only implemented for a couple of matrix formats.
5055 
5056 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5057 @*/
5058 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5059 {
5060   PetscFunctionBegin;
5061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5062   PetscValidType(mat, 1);
5063   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5065 
5066   if (!mat->cmap->N) {
5067     PetscCall(VecSet(v, PETSC_MIN_REAL));
5068     if (idx) {
5069       PetscInt i, m = mat->rmap->n;
5070       for (i = 0; i < m; i++) idx[i] = -1;
5071     }
5072   } else {
5073     MatCheckPreallocated(mat, 1);
5074     PetscUseTypeMethod(mat, getrowmax, v, idx);
5075   }
5076   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5077   PetscFunctionReturn(PETSC_SUCCESS);
5078 }
5079 
5080 /*@C
5081   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5082   row of the matrix
5083 
5084   Logically Collective
5085 
5086   Input Parameter:
5087 . mat - the matrix
5088 
5089   Output Parameters:
5090 + v   - the vector for storing the maximums
5091 - idx - the indices of the column found for each row (or `NULL` if not needed)
5092 
5093   Level: intermediate
5094 
5095   Notes:
5096   if a row is completely empty or has only 0.0 values then the `idx` value for that
5097   row is 0 (the first column).
5098 
5099   This code is only implemented for a couple of matrix formats.
5100 
5101 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5102 @*/
5103 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5104 {
5105   PetscFunctionBegin;
5106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5107   PetscValidType(mat, 1);
5108   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5109   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5110 
5111   if (!mat->cmap->N) {
5112     PetscCall(VecSet(v, 0.0));
5113     if (idx) {
5114       PetscInt i, m = mat->rmap->n;
5115       for (i = 0; i < m; i++) idx[i] = -1;
5116     }
5117   } else {
5118     MatCheckPreallocated(mat, 1);
5119     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5120     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5121   }
5122   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5123   PetscFunctionReturn(PETSC_SUCCESS);
5124 }
5125 
5126 /*@
5127   MatGetRowSum - Gets the sum of each row of the matrix
5128 
5129   Logically or Neighborhood Collective
5130 
5131   Input Parameter:
5132 . mat - the matrix
5133 
5134   Output Parameter:
5135 . v - the vector for storing the sum of rows
5136 
5137   Level: intermediate
5138 
5139   Note:
5140   This code is slow since it is not currently specialized for different formats
5141 
5142 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5143 @*/
5144 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5145 {
5146   Vec ones;
5147 
5148   PetscFunctionBegin;
5149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5150   PetscValidType(mat, 1);
5151   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5153   MatCheckPreallocated(mat, 1);
5154   PetscCall(MatCreateVecs(mat, &ones, NULL));
5155   PetscCall(VecSet(ones, 1.));
5156   PetscCall(MatMult(mat, ones, v));
5157   PetscCall(VecDestroy(&ones));
5158   PetscFunctionReturn(PETSC_SUCCESS);
5159 }
5160 
5161 /*@
5162   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5163   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5164 
5165   Collective
5166 
5167   Input Parameter:
5168 . mat - the matrix to provide the transpose
5169 
5170   Output Parameter:
5171 . B - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results
5172 
5173   Level: advanced
5174 
5175   Note:
5176   Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5177   routine allows bypassing that call.
5178 
5179 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5180 @*/
5181 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5182 {
5183   PetscContainer  rB = NULL;
5184   MatParentState *rb = NULL;
5185 
5186   PetscFunctionBegin;
5187   PetscCall(PetscNew(&rb));
5188   rb->id    = ((PetscObject)mat)->id;
5189   rb->state = 0;
5190   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5191   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5192   PetscCall(PetscContainerSetPointer(rB, rb));
5193   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5194   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5195   PetscCall(PetscObjectDereference((PetscObject)rB));
5196   PetscFunctionReturn(PETSC_SUCCESS);
5197 }
5198 
5199 /*@
5200   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5201 
5202   Collective
5203 
5204   Input Parameters:
5205 + mat   - the matrix to transpose
5206 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5207 
5208   Output Parameter:
5209 . B - the transpose
5210 
5211   Level: intermediate
5212 
5213   Notes:
5214   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5215 
5216   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5217   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5218 
5219   If the nonzero structure of mat changed from the previous call to this function with the same matrices an error will be generated for some matrix types.
5220 
5221   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5222 
5223   If mat is unchanged from the last call this function returns immediately without recomputing the result
5224 
5225   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5226 
5227 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5228           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5229 @*/
5230 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5231 {
5232   PetscContainer  rB = NULL;
5233   MatParentState *rb = NULL;
5234 
5235   PetscFunctionBegin;
5236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5237   PetscValidType(mat, 1);
5238   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5239   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5240   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5241   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5242   MatCheckPreallocated(mat, 1);
5243   if (reuse == MAT_REUSE_MATRIX) {
5244     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5245     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5246     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5247     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5248     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5249   }
5250 
5251   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5252   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5253     PetscUseTypeMethod(mat, transpose, reuse, B);
5254     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5255   }
5256   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5257 
5258   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5259   if (reuse != MAT_INPLACE_MATRIX) {
5260     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5261     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5262     rb->state        = ((PetscObject)mat)->state;
5263     rb->nonzerostate = mat->nonzerostate;
5264   }
5265   PetscFunctionReturn(PETSC_SUCCESS);
5266 }
5267 
5268 /*@
5269   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5270 
5271   Collective
5272 
5273   Input Parameter:
5274 . A - the matrix to transpose
5275 
5276   Output Parameter:
5277 . B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the
5278       numerical portion.
5279 
5280   Level: intermediate
5281 
5282   Note:
5283   This is not supported for many matrix types, use `MatTranspose()` in those cases
5284 
5285 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5286 @*/
5287 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5288 {
5289   PetscFunctionBegin;
5290   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5291   PetscValidType(A, 1);
5292   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5293   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5294   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5295   PetscUseTypeMethod(A, transposesymbolic, B);
5296   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5297 
5298   PetscCall(MatTransposeSetPrecursor(A, *B));
5299   PetscFunctionReturn(PETSC_SUCCESS);
5300 }
5301 
5302 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5303 {
5304   PetscContainer  rB;
5305   MatParentState *rb;
5306 
5307   PetscFunctionBegin;
5308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5309   PetscValidType(A, 1);
5310   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5311   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5312   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5313   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5314   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5315   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5316   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5317   PetscFunctionReturn(PETSC_SUCCESS);
5318 }
5319 
5320 /*@
5321   MatIsTranspose - Test whether a matrix is another one's transpose,
5322   or its own, in which case it tests symmetry.
5323 
5324   Collective
5325 
5326   Input Parameters:
5327 + A   - the matrix to test
5328 . B   - the matrix to test against, this can equal the first parameter
5329 - tol - tolerance, differences between entries smaller than this are counted as zero
5330 
5331   Output Parameter:
5332 . flg - the result
5333 
5334   Level: intermediate
5335 
5336   Notes:
5337   Only available for `MATAIJ` matrices.
5338 
5339   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5340   test involves parallel copies of the block off-diagonal parts of the matrix.
5341 
5342 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5343 @*/
5344 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5345 {
5346   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5347 
5348   PetscFunctionBegin;
5349   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5350   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5351   PetscAssertPointer(flg, 4);
5352   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5353   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5354   *flg = PETSC_FALSE;
5355   if (f && g) {
5356     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5357     PetscCall((*f)(A, B, tol, flg));
5358   } else {
5359     MatType mattype;
5360 
5361     PetscCall(MatGetType(f ? B : A, &mattype));
5362     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5363   }
5364   PetscFunctionReturn(PETSC_SUCCESS);
5365 }
5366 
5367 /*@
5368   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5369 
5370   Collective
5371 
5372   Input Parameters:
5373 + mat   - the matrix to transpose and complex conjugate
5374 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5375 
5376   Output Parameter:
5377 . B - the Hermitian transpose
5378 
5379   Level: intermediate
5380 
5381 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5382 @*/
5383 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5384 {
5385   PetscFunctionBegin;
5386   PetscCall(MatTranspose(mat, reuse, B));
5387 #if defined(PETSC_USE_COMPLEX)
5388   PetscCall(MatConjugate(*B));
5389 #endif
5390   PetscFunctionReturn(PETSC_SUCCESS);
5391 }
5392 
5393 /*@
5394   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5395 
5396   Collective
5397 
5398   Input Parameters:
5399 + A   - the matrix to test
5400 . B   - the matrix to test against, this can equal the first parameter
5401 - tol - tolerance, differences between entries smaller than this are counted as zero
5402 
5403   Output Parameter:
5404 . flg - the result
5405 
5406   Level: intermediate
5407 
5408   Notes:
5409   Only available for `MATAIJ` matrices.
5410 
5411   The sequential algorithm
5412   has a running time of the order of the number of nonzeros; the parallel
5413   test involves parallel copies of the block off-diagonal parts of the matrix.
5414 
5415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5416 @*/
5417 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5418 {
5419   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5420 
5421   PetscFunctionBegin;
5422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5423   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5424   PetscAssertPointer(flg, 4);
5425   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5426   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5427   if (f && g) {
5428     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5429     PetscCall((*f)(A, B, tol, flg));
5430   }
5431   PetscFunctionReturn(PETSC_SUCCESS);
5432 }
5433 
5434 /*@
5435   MatPermute - Creates a new matrix with rows and columns permuted from the
5436   original.
5437 
5438   Collective
5439 
5440   Input Parameters:
5441 + mat - the matrix to permute
5442 . row - row permutation, each processor supplies only the permutation for its rows
5443 - col - column permutation, each processor supplies only the permutation for its columns
5444 
5445   Output Parameter:
5446 . B - the permuted matrix
5447 
5448   Level: advanced
5449 
5450   Note:
5451   The index sets map from row/col of permuted matrix to row/col of original matrix.
5452   The index sets should be on the same communicator as mat and have the same local sizes.
5453 
5454   Developer Note:
5455   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5456   exploit the fact that row and col are permutations, consider implementing the
5457   more general `MatCreateSubMatrix()` instead.
5458 
5459 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5460 @*/
5461 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5462 {
5463   PetscFunctionBegin;
5464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5465   PetscValidType(mat, 1);
5466   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5467   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5468   PetscAssertPointer(B, 4);
5469   PetscCheckSameComm(mat, 1, row, 2);
5470   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5471   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5472   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5473   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5474   MatCheckPreallocated(mat, 1);
5475 
5476   if (mat->ops->permute) {
5477     PetscUseTypeMethod(mat, permute, row, col, B);
5478     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5479   } else {
5480     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5481   }
5482   PetscFunctionReturn(PETSC_SUCCESS);
5483 }
5484 
5485 /*@
5486   MatEqual - Compares two matrices.
5487 
5488   Collective
5489 
5490   Input Parameters:
5491 + A - the first matrix
5492 - B - the second matrix
5493 
5494   Output Parameter:
5495 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5496 
5497   Level: intermediate
5498 
5499 .seealso: [](ch_matrices), `Mat`
5500 @*/
5501 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5502 {
5503   PetscFunctionBegin;
5504   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5505   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5506   PetscValidType(A, 1);
5507   PetscValidType(B, 2);
5508   PetscAssertPointer(flg, 3);
5509   PetscCheckSameComm(A, 1, B, 2);
5510   MatCheckPreallocated(A, 1);
5511   MatCheckPreallocated(B, 2);
5512   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5513   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5514   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5515              B->cmap->N);
5516   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5517     PetscUseTypeMethod(A, equal, B, flg);
5518   } else {
5519     PetscCall(MatMultEqual(A, B, 10, flg));
5520   }
5521   PetscFunctionReturn(PETSC_SUCCESS);
5522 }
5523 
5524 /*@
5525   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5526   matrices that are stored as vectors.  Either of the two scaling
5527   matrices can be `NULL`.
5528 
5529   Collective
5530 
5531   Input Parameters:
5532 + mat - the matrix to be scaled
5533 . l   - the left scaling vector (or `NULL`)
5534 - r   - the right scaling vector (or `NULL`)
5535 
5536   Level: intermediate
5537 
5538   Note:
5539   `MatDiagonalScale()` computes $A = LAR$, where
5540   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5541   The L scales the rows of the matrix, the R scales the columns of the matrix.
5542 
5543 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5544 @*/
5545 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5546 {
5547   PetscFunctionBegin;
5548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5549   PetscValidType(mat, 1);
5550   if (l) {
5551     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5552     PetscCheckSameComm(mat, 1, l, 2);
5553   }
5554   if (r) {
5555     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5556     PetscCheckSameComm(mat, 1, r, 3);
5557   }
5558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5559   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5560   MatCheckPreallocated(mat, 1);
5561   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5562 
5563   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5564   PetscUseTypeMethod(mat, diagonalscale, l, r);
5565   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5566   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5567   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5568   PetscFunctionReturn(PETSC_SUCCESS);
5569 }
5570 
5571 /*@
5572   MatScale - Scales all elements of a matrix by a given number.
5573 
5574   Logically Collective
5575 
5576   Input Parameters:
5577 + mat - the matrix to be scaled
5578 - a   - the scaling value
5579 
5580   Level: intermediate
5581 
5582 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5583 @*/
5584 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5585 {
5586   PetscFunctionBegin;
5587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5588   PetscValidType(mat, 1);
5589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5591   PetscValidLogicalCollectiveScalar(mat, a, 2);
5592   MatCheckPreallocated(mat, 1);
5593 
5594   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5595   if (a != (PetscScalar)1.0) {
5596     PetscUseTypeMethod(mat, scale, a);
5597     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5598   }
5599   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5600   PetscFunctionReturn(PETSC_SUCCESS);
5601 }
5602 
5603 /*@
5604   MatNorm - Calculates various norms of a matrix.
5605 
5606   Collective
5607 
5608   Input Parameters:
5609 + mat  - the matrix
5610 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5611 
5612   Output Parameter:
5613 . nrm - the resulting norm
5614 
5615   Level: intermediate
5616 
5617 .seealso: [](ch_matrices), `Mat`
5618 @*/
5619 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5620 {
5621   PetscFunctionBegin;
5622   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5623   PetscValidType(mat, 1);
5624   PetscAssertPointer(nrm, 3);
5625 
5626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5627   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5628   MatCheckPreallocated(mat, 1);
5629 
5630   PetscUseTypeMethod(mat, norm, type, nrm);
5631   PetscFunctionReturn(PETSC_SUCCESS);
5632 }
5633 
5634 /*
5635      This variable is used to prevent counting of MatAssemblyBegin() that
5636    are called from within a MatAssemblyEnd().
5637 */
5638 static PetscInt MatAssemblyEnd_InUse = 0;
5639 /*@
5640   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5641   be called after completing all calls to `MatSetValues()`.
5642 
5643   Collective
5644 
5645   Input Parameters:
5646 + mat  - the matrix
5647 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5648 
5649   Level: beginner
5650 
5651   Notes:
5652   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5653   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5654 
5655   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5656   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5657   using the matrix.
5658 
5659   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5660   same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is
5661   a global collective operation requiring all processes that share the matrix.
5662 
5663   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5664   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5665   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5666 
5667 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5668 @*/
5669 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5670 {
5671   PetscFunctionBegin;
5672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5673   PetscValidType(mat, 1);
5674   MatCheckPreallocated(mat, 1);
5675   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5676   if (mat->assembled) {
5677     mat->was_assembled = PETSC_TRUE;
5678     mat->assembled     = PETSC_FALSE;
5679   }
5680 
5681   if (!MatAssemblyEnd_InUse) {
5682     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5683     PetscTryTypeMethod(mat, assemblybegin, type);
5684     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5685   } else PetscTryTypeMethod(mat, assemblybegin, type);
5686   PetscFunctionReturn(PETSC_SUCCESS);
5687 }
5688 
5689 /*@
5690   MatAssembled - Indicates if a matrix has been assembled and is ready for
5691   use; for example, in matrix-vector product.
5692 
5693   Not Collective
5694 
5695   Input Parameter:
5696 . mat - the matrix
5697 
5698   Output Parameter:
5699 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5700 
5701   Level: advanced
5702 
5703 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5704 @*/
5705 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5706 {
5707   PetscFunctionBegin;
5708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5709   PetscAssertPointer(assembled, 2);
5710   *assembled = mat->assembled;
5711   PetscFunctionReturn(PETSC_SUCCESS);
5712 }
5713 
5714 /*@
5715   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5716   be called after `MatAssemblyBegin()`.
5717 
5718   Collective
5719 
5720   Input Parameters:
5721 + mat  - the matrix
5722 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5723 
5724   Options Database Keys:
5725 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5726 . -mat_view ::ascii_info_detail      - Prints more detailed info
5727 . -mat_view                          - Prints matrix in ASCII format
5728 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5729 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5730 . -display <name>                    - Sets display name (default is host)
5731 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5732 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5733 . -viewer_socket_machine <machine>   - Machine to use for socket
5734 . -viewer_socket_port <port>         - Port number to use for socket
5735 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5736 
5737   Level: beginner
5738 
5739 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5740 @*/
5741 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5742 {
5743   static PetscInt inassm = 0;
5744   PetscBool       flg    = PETSC_FALSE;
5745 
5746   PetscFunctionBegin;
5747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5748   PetscValidType(mat, 1);
5749 
5750   inassm++;
5751   MatAssemblyEnd_InUse++;
5752   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5753     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5754     PetscTryTypeMethod(mat, assemblyend, type);
5755     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5756   } else PetscTryTypeMethod(mat, assemblyend, type);
5757 
5758   /* Flush assembly is not a true assembly */
5759   if (type != MAT_FLUSH_ASSEMBLY) {
5760     if (mat->num_ass) {
5761       if (!mat->symmetry_eternal) {
5762         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5763         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5764       }
5765       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5766       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5767     }
5768     mat->num_ass++;
5769     mat->assembled        = PETSC_TRUE;
5770     mat->ass_nonzerostate = mat->nonzerostate;
5771   }
5772 
5773   mat->insertmode = NOT_SET_VALUES;
5774   MatAssemblyEnd_InUse--;
5775   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5776   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5777     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5778 
5779     if (mat->checksymmetryonassembly) {
5780       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5781       if (flg) {
5782         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5783       } else {
5784         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5785       }
5786     }
5787     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5788   }
5789   inassm--;
5790   PetscFunctionReturn(PETSC_SUCCESS);
5791 }
5792 
5793 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5794 /*@
5795   MatSetOption - Sets a parameter option for a matrix. Some options
5796   may be specific to certain storage formats.  Some options
5797   determine how values will be inserted (or added). Sorted,
5798   row-oriented input will generally assemble the fastest. The default
5799   is row-oriented.
5800 
5801   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5802 
5803   Input Parameters:
5804 + mat - the matrix
5805 . op  - the option, one of those listed below (and possibly others),
5806 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5807 
5808   Options Describing Matrix Structure:
5809 + `MAT_SPD`                         - symmetric positive definite
5810 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5811 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5812 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5813 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5814 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5815 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5816 
5817    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5818    do not need to be computed (usually at a high cost)
5819 
5820    Options For Use with `MatSetValues()`:
5821    Insert a logically dense subblock, which can be
5822 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5823 
5824    These options reflect the data you pass in with `MatSetValues()`; it has
5825    nothing to do with how the data is stored internally in the matrix
5826    data structure.
5827 
5828    When (re)assembling a matrix, we can restrict the input for
5829    efficiency/debugging purposes.  These options include
5830 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5831 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5832 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5833 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5834 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5835 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5836         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5837         performance for very large process counts.
5838 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5839         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5840         functions, instead sending only neighbor messages.
5841 
5842   Level: intermediate
5843 
5844   Notes:
5845   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5846 
5847   Some options are relevant only for particular matrix types and
5848   are thus ignored by others.  Other options are not supported by
5849   certain matrix types and will generate an error message if set.
5850 
5851   If using Fortran to compute a matrix, one may need to
5852   use the column-oriented option (or convert to the row-oriented
5853   format).
5854 
5855   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5856   that would generate a new entry in the nonzero structure is instead
5857   ignored.  Thus, if memory has not already been allocated for this particular
5858   data, then the insertion is ignored. For dense matrices, in which
5859   the entire array is allocated, no entries are ever ignored.
5860   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5861 
5862   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5863   that would generate a new entry in the nonzero structure instead produces
5864   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
5865 
5866   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5867   that would generate a new entry that has not been preallocated will
5868   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5869   only.) This is a useful flag when debugging matrix memory preallocation.
5870   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5871 
5872   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5873   other processors should be dropped, rather than stashed.
5874   This is useful if you know that the "owning" processor is also
5875   always generating the correct matrix entries, so that PETSc need
5876   not transfer duplicate entries generated on another processor.
5877 
5878   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5879   searches during matrix assembly. When this flag is set, the hash table
5880   is created during the first matrix assembly. This hash table is
5881   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5882   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5883   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5884   supported by `MATMPIBAIJ` format only.
5885 
5886   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5887   are kept in the nonzero structure
5888 
5889   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5890   a zero location in the matrix
5891 
5892   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5893 
5894   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5895   zero row routines and thus improves performance for very large process counts.
5896 
5897   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5898   part of the matrix (since they should match the upper triangular part).
5899 
5900   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5901   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5902   with finite difference schemes with non-periodic boundary conditions.
5903 
5904   Developer Note:
5905   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5906   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5907   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5908   not changed.
5909 
5910 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5911 @*/
5912 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5913 {
5914   PetscFunctionBegin;
5915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5916   if (op > 0) {
5917     PetscValidLogicalCollectiveEnum(mat, op, 2);
5918     PetscValidLogicalCollectiveBool(mat, flg, 3);
5919   }
5920 
5921   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);
5922 
5923   switch (op) {
5924   case MAT_FORCE_DIAGONAL_ENTRIES:
5925     mat->force_diagonals = flg;
5926     PetscFunctionReturn(PETSC_SUCCESS);
5927   case MAT_NO_OFF_PROC_ENTRIES:
5928     mat->nooffprocentries = flg;
5929     PetscFunctionReturn(PETSC_SUCCESS);
5930   case MAT_SUBSET_OFF_PROC_ENTRIES:
5931     mat->assembly_subset = flg;
5932     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5933 #if !defined(PETSC_HAVE_MPIUNI)
5934       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5935 #endif
5936       mat->stash.first_assembly_done = PETSC_FALSE;
5937     }
5938     PetscFunctionReturn(PETSC_SUCCESS);
5939   case MAT_NO_OFF_PROC_ZERO_ROWS:
5940     mat->nooffproczerorows = flg;
5941     PetscFunctionReturn(PETSC_SUCCESS);
5942   case MAT_SPD:
5943     if (flg) {
5944       mat->spd                    = PETSC_BOOL3_TRUE;
5945       mat->symmetric              = PETSC_BOOL3_TRUE;
5946       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5947     } else {
5948       mat->spd = PETSC_BOOL3_FALSE;
5949     }
5950     break;
5951   case MAT_SYMMETRIC:
5952     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5953     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5954 #if !defined(PETSC_USE_COMPLEX)
5955     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5956 #endif
5957     break;
5958   case MAT_HERMITIAN:
5959     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5960     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5961 #if !defined(PETSC_USE_COMPLEX)
5962     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5963 #endif
5964     break;
5965   case MAT_STRUCTURALLY_SYMMETRIC:
5966     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5967     break;
5968   case MAT_SYMMETRY_ETERNAL:
5969     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");
5970     mat->symmetry_eternal = flg;
5971     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5972     break;
5973   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5974     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false");
5975     mat->structural_symmetry_eternal = flg;
5976     break;
5977   case MAT_SPD_ETERNAL:
5978     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");
5979     mat->spd_eternal = flg;
5980     if (flg) {
5981       mat->structural_symmetry_eternal = PETSC_TRUE;
5982       mat->symmetry_eternal            = PETSC_TRUE;
5983     }
5984     break;
5985   case MAT_STRUCTURE_ONLY:
5986     mat->structure_only = flg;
5987     break;
5988   case MAT_SORTED_FULL:
5989     mat->sortedfull = flg;
5990     break;
5991   default:
5992     break;
5993   }
5994   PetscTryTypeMethod(mat, setoption, op, flg);
5995   PetscFunctionReturn(PETSC_SUCCESS);
5996 }
5997 
5998 /*@
5999   MatGetOption - Gets a parameter option that has been set for a matrix.
6000 
6001   Logically Collective
6002 
6003   Input Parameters:
6004 + mat - the matrix
6005 - op  - the option, this only responds to certain options, check the code for which ones
6006 
6007   Output Parameter:
6008 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6009 
6010   Level: intermediate
6011 
6012   Notes:
6013   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6014 
6015   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6016   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6017 
6018 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6019     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6020 @*/
6021 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6022 {
6023   PetscFunctionBegin;
6024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6025   PetscValidType(mat, 1);
6026 
6027   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);
6028   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()");
6029 
6030   switch (op) {
6031   case MAT_NO_OFF_PROC_ENTRIES:
6032     *flg = mat->nooffprocentries;
6033     break;
6034   case MAT_NO_OFF_PROC_ZERO_ROWS:
6035     *flg = mat->nooffproczerorows;
6036     break;
6037   case MAT_SYMMETRIC:
6038     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6039     break;
6040   case MAT_HERMITIAN:
6041     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6042     break;
6043   case MAT_STRUCTURALLY_SYMMETRIC:
6044     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6045     break;
6046   case MAT_SPD:
6047     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6048     break;
6049   case MAT_SYMMETRY_ETERNAL:
6050     *flg = mat->symmetry_eternal;
6051     break;
6052   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6053     *flg = mat->symmetry_eternal;
6054     break;
6055   default:
6056     break;
6057   }
6058   PetscFunctionReturn(PETSC_SUCCESS);
6059 }
6060 
6061 /*@
6062   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6063   this routine retains the old nonzero structure.
6064 
6065   Logically Collective
6066 
6067   Input Parameter:
6068 . mat - the matrix
6069 
6070   Level: intermediate
6071 
6072   Note:
6073   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.
6074   See the Performance chapter of the users manual for information on preallocating matrices.
6075 
6076 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6077 @*/
6078 PetscErrorCode MatZeroEntries(Mat mat)
6079 {
6080   PetscFunctionBegin;
6081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6082   PetscValidType(mat, 1);
6083   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6084   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");
6085   MatCheckPreallocated(mat, 1);
6086 
6087   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6088   PetscUseTypeMethod(mat, zeroentries);
6089   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6090   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6091   PetscFunctionReturn(PETSC_SUCCESS);
6092 }
6093 
6094 /*@
6095   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6096   of a set of rows and columns of a matrix.
6097 
6098   Collective
6099 
6100   Input Parameters:
6101 + mat     - the matrix
6102 . numRows - the number of rows/columns to zero
6103 . rows    - the global row indices
6104 . diag    - value put in the diagonal of the eliminated rows
6105 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6106 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6107 
6108   Level: intermediate
6109 
6110   Notes:
6111   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6112 
6113   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6114   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
6115 
6116   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6117   Krylov method to take advantage of the known solution on the zeroed rows.
6118 
6119   For the parallel case, all processes that share the matrix (i.e.,
6120   those in the communicator used for matrix creation) MUST call this
6121   routine, regardless of whether any rows being zeroed are owned by
6122   them.
6123 
6124   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6125 
6126   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6127   list only rows local to itself).
6128 
6129   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6130 
6131 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6132           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6133 @*/
6134 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6135 {
6136   PetscFunctionBegin;
6137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6138   PetscValidType(mat, 1);
6139   if (numRows) PetscAssertPointer(rows, 3);
6140   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6141   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6142   MatCheckPreallocated(mat, 1);
6143 
6144   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6145   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6146   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6147   PetscFunctionReturn(PETSC_SUCCESS);
6148 }
6149 
6150 /*@
6151   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6152   of a set of rows and columns of a matrix.
6153 
6154   Collective
6155 
6156   Input Parameters:
6157 + mat  - the matrix
6158 . is   - the rows to zero
6159 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6160 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6161 - b    - optional vector of right hand side, that will be adjusted by provided solution
6162 
6163   Level: intermediate
6164 
6165   Note:
6166   See `MatZeroRowsColumns()` for details on how this routine operates.
6167 
6168 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6169           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6170 @*/
6171 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6172 {
6173   PetscInt        numRows;
6174   const PetscInt *rows;
6175 
6176   PetscFunctionBegin;
6177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6178   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6179   PetscValidType(mat, 1);
6180   PetscValidType(is, 2);
6181   PetscCall(ISGetLocalSize(is, &numRows));
6182   PetscCall(ISGetIndices(is, &rows));
6183   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6184   PetscCall(ISRestoreIndices(is, &rows));
6185   PetscFunctionReturn(PETSC_SUCCESS);
6186 }
6187 
6188 /*@
6189   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6190   of a set of rows of a matrix.
6191 
6192   Collective
6193 
6194   Input Parameters:
6195 + mat     - the matrix
6196 . numRows - the number of rows to zero
6197 . rows    - the global row indices
6198 . diag    - value put in the diagonal of the zeroed rows
6199 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6200 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6201 
6202   Level: intermediate
6203 
6204   Notes:
6205   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6206 
6207   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6208 
6209   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6210   Krylov method to take advantage of the known solution on the zeroed rows.
6211 
6212   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)
6213   from the matrix.
6214 
6215   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6216   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
6217   formats this does not alter the nonzero structure.
6218 
6219   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6220   of the matrix is not changed the values are
6221   merely zeroed.
6222 
6223   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6224   formats can optionally remove the main diagonal entry from the
6225   nonzero structure as well, by passing 0.0 as the final argument).
6226 
6227   For the parallel case, all processes that share the matrix (i.e.,
6228   those in the communicator used for matrix creation) MUST call this
6229   routine, regardless of whether any rows being zeroed are owned by
6230   them.
6231 
6232   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6233   list only rows local to itself).
6234 
6235   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6236   owns that are to be zeroed. This saves a global synchronization in the implementation.
6237 
6238 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6239           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6240 @*/
6241 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6242 {
6243   PetscFunctionBegin;
6244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6245   PetscValidType(mat, 1);
6246   if (numRows) PetscAssertPointer(rows, 3);
6247   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6249   MatCheckPreallocated(mat, 1);
6250 
6251   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6252   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6253   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6254   PetscFunctionReturn(PETSC_SUCCESS);
6255 }
6256 
6257 /*@
6258   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6259   of a set of rows of a matrix.
6260 
6261   Collective
6262 
6263   Input Parameters:
6264 + mat  - the matrix
6265 . is   - index set of rows to remove (if `NULL` then no row is removed)
6266 . diag - value put in all diagonals of eliminated rows
6267 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6268 - b    - optional vector of right hand side, that will be adjusted by provided solution
6269 
6270   Level: intermediate
6271 
6272   Note:
6273   See `MatZeroRows()` for details on how this routine operates.
6274 
6275 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6276           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6277 @*/
6278 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6279 {
6280   PetscInt        numRows = 0;
6281   const PetscInt *rows    = NULL;
6282 
6283   PetscFunctionBegin;
6284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6285   PetscValidType(mat, 1);
6286   if (is) {
6287     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6288     PetscCall(ISGetLocalSize(is, &numRows));
6289     PetscCall(ISGetIndices(is, &rows));
6290   }
6291   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6292   if (is) PetscCall(ISRestoreIndices(is, &rows));
6293   PetscFunctionReturn(PETSC_SUCCESS);
6294 }
6295 
6296 /*@
6297   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6298   of a set of rows of a matrix. These rows must be local to the process.
6299 
6300   Collective
6301 
6302   Input Parameters:
6303 + mat     - the matrix
6304 . numRows - the number of rows to remove
6305 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6306 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6307 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6308 - b       - optional vector of right hand side, that will be adjusted by provided solution
6309 
6310   Level: intermediate
6311 
6312   Notes:
6313   See `MatZeroRows()` for details on how this routine operates.
6314 
6315   The grid coordinates are across the entire grid, not just the local portion
6316 
6317   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6318   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6319   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6320   `DM_BOUNDARY_PERIODIC` boundary type.
6321 
6322   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
6323   a single value per point) you can skip filling those indices.
6324 
6325   Fortran Note:
6326   `idxm` and `idxn` should be declared as
6327 $     MatStencil idxm(4, m)
6328   and the values inserted using
6329 .vb
6330     idxm(MatStencil_i, 1) = i
6331     idxm(MatStencil_j, 1) = j
6332     idxm(MatStencil_k, 1) = k
6333     idxm(MatStencil_c, 1) = c
6334    etc
6335 .ve
6336 
6337 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6338           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6339 @*/
6340 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6341 {
6342   PetscInt  dim    = mat->stencil.dim;
6343   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6344   PetscInt *dims   = mat->stencil.dims + 1;
6345   PetscInt *starts = mat->stencil.starts;
6346   PetscInt *dxm    = (PetscInt *)rows;
6347   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6348 
6349   PetscFunctionBegin;
6350   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6351   PetscValidType(mat, 1);
6352   if (numRows) PetscAssertPointer(rows, 3);
6353 
6354   PetscCall(PetscMalloc1(numRows, &jdxm));
6355   for (i = 0; i < numRows; ++i) {
6356     /* Skip unused dimensions (they are ordered k, j, i, c) */
6357     for (j = 0; j < 3 - sdim; ++j) dxm++;
6358     /* Local index in X dir */
6359     tmp = *dxm++ - starts[0];
6360     /* Loop over remaining dimensions */
6361     for (j = 0; j < dim - 1; ++j) {
6362       /* If nonlocal, set index to be negative */
6363       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6364       /* Update local index */
6365       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6366     }
6367     /* Skip component slot if necessary */
6368     if (mat->stencil.noc) dxm++;
6369     /* Local row number */
6370     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6371   }
6372   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6373   PetscCall(PetscFree(jdxm));
6374   PetscFunctionReturn(PETSC_SUCCESS);
6375 }
6376 
6377 /*@
6378   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6379   of a set of rows and columns of a matrix.
6380 
6381   Collective
6382 
6383   Input Parameters:
6384 + mat     - the matrix
6385 . numRows - the number of rows/columns to remove
6386 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6387 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6388 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6389 - b       - optional vector of right hand side, that will be adjusted by provided solution
6390 
6391   Level: intermediate
6392 
6393   Notes:
6394   See `MatZeroRowsColumns()` for details on how this routine operates.
6395 
6396   The grid coordinates are across the entire grid, not just the local portion
6397 
6398   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6399   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6400   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6401   `DM_BOUNDARY_PERIODIC` boundary type.
6402 
6403   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
6404   a single value per point) you can skip filling those indices.
6405 
6406   Fortran Note:
6407   `idxm` and `idxn` should be declared as
6408 $     MatStencil idxm(4, m)
6409   and the values inserted using
6410 .vb
6411     idxm(MatStencil_i, 1) = i
6412     idxm(MatStencil_j, 1) = j
6413     idxm(MatStencil_k, 1) = k
6414     idxm(MatStencil_c, 1) = c
6415     etc
6416 .ve
6417 
6418 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6419           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6420 @*/
6421 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6422 {
6423   PetscInt  dim    = mat->stencil.dim;
6424   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6425   PetscInt *dims   = mat->stencil.dims + 1;
6426   PetscInt *starts = mat->stencil.starts;
6427   PetscInt *dxm    = (PetscInt *)rows;
6428   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6429 
6430   PetscFunctionBegin;
6431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6432   PetscValidType(mat, 1);
6433   if (numRows) PetscAssertPointer(rows, 3);
6434 
6435   PetscCall(PetscMalloc1(numRows, &jdxm));
6436   for (i = 0; i < numRows; ++i) {
6437     /* Skip unused dimensions (they are ordered k, j, i, c) */
6438     for (j = 0; j < 3 - sdim; ++j) dxm++;
6439     /* Local index in X dir */
6440     tmp = *dxm++ - starts[0];
6441     /* Loop over remaining dimensions */
6442     for (j = 0; j < dim - 1; ++j) {
6443       /* If nonlocal, set index to be negative */
6444       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6445       /* Update local index */
6446       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6447     }
6448     /* Skip component slot if necessary */
6449     if (mat->stencil.noc) dxm++;
6450     /* Local row number */
6451     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6452   }
6453   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6454   PetscCall(PetscFree(jdxm));
6455   PetscFunctionReturn(PETSC_SUCCESS);
6456 }
6457 
6458 /*@C
6459   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6460   of a set of rows of a matrix; using local numbering of rows.
6461 
6462   Collective
6463 
6464   Input Parameters:
6465 + mat     - the matrix
6466 . numRows - the number of rows to remove
6467 . rows    - the local row indices
6468 . diag    - value put in all diagonals of eliminated rows
6469 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6470 - b       - optional vector of right hand side, that will be adjusted by provided solution
6471 
6472   Level: intermediate
6473 
6474   Notes:
6475   Before calling `MatZeroRowsLocal()`, the user must first set the
6476   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6477 
6478   See `MatZeroRows()` for details on how this routine operates.
6479 
6480 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6481           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6482 @*/
6483 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6484 {
6485   PetscFunctionBegin;
6486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6487   PetscValidType(mat, 1);
6488   if (numRows) PetscAssertPointer(rows, 3);
6489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6491   MatCheckPreallocated(mat, 1);
6492 
6493   if (mat->ops->zerorowslocal) {
6494     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6495   } else {
6496     IS              is, newis;
6497     const PetscInt *newRows;
6498 
6499     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6500     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6501     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6502     PetscCall(ISGetIndices(newis, &newRows));
6503     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6504     PetscCall(ISRestoreIndices(newis, &newRows));
6505     PetscCall(ISDestroy(&newis));
6506     PetscCall(ISDestroy(&is));
6507   }
6508   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6509   PetscFunctionReturn(PETSC_SUCCESS);
6510 }
6511 
6512 /*@
6513   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6514   of a set of rows of a matrix; using local numbering of rows.
6515 
6516   Collective
6517 
6518   Input Parameters:
6519 + mat  - the matrix
6520 . is   - index set of rows to remove
6521 . diag - value put in all diagonals of eliminated rows
6522 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6523 - b    - optional vector of right hand side, that will be adjusted by provided solution
6524 
6525   Level: intermediate
6526 
6527   Notes:
6528   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6529   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6530 
6531   See `MatZeroRows()` for details on how this routine operates.
6532 
6533 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6534           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6535 @*/
6536 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6537 {
6538   PetscInt        numRows;
6539   const PetscInt *rows;
6540 
6541   PetscFunctionBegin;
6542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6543   PetscValidType(mat, 1);
6544   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6547   MatCheckPreallocated(mat, 1);
6548 
6549   PetscCall(ISGetLocalSize(is, &numRows));
6550   PetscCall(ISGetIndices(is, &rows));
6551   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6552   PetscCall(ISRestoreIndices(is, &rows));
6553   PetscFunctionReturn(PETSC_SUCCESS);
6554 }
6555 
6556 /*@
6557   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6558   of a set of rows and columns of a matrix; using local numbering of rows.
6559 
6560   Collective
6561 
6562   Input Parameters:
6563 + mat     - the matrix
6564 . numRows - the number of rows to remove
6565 . rows    - the global row indices
6566 . diag    - value put in all diagonals of eliminated rows
6567 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6568 - b       - optional vector of right hand side, that will be adjusted by provided solution
6569 
6570   Level: intermediate
6571 
6572   Notes:
6573   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6574   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6575 
6576   See `MatZeroRowsColumns()` for details on how this routine operates.
6577 
6578 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6579           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6580 @*/
6581 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6582 {
6583   IS              is, newis;
6584   const PetscInt *newRows;
6585 
6586   PetscFunctionBegin;
6587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6588   PetscValidType(mat, 1);
6589   if (numRows) PetscAssertPointer(rows, 3);
6590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6592   MatCheckPreallocated(mat, 1);
6593 
6594   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6595   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6596   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6597   PetscCall(ISGetIndices(newis, &newRows));
6598   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6599   PetscCall(ISRestoreIndices(newis, &newRows));
6600   PetscCall(ISDestroy(&newis));
6601   PetscCall(ISDestroy(&is));
6602   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6603   PetscFunctionReturn(PETSC_SUCCESS);
6604 }
6605 
6606 /*@
6607   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6608   of a set of rows and columns of a matrix; using local numbering of rows.
6609 
6610   Collective
6611 
6612   Input Parameters:
6613 + mat  - the matrix
6614 . is   - index set of rows to remove
6615 . diag - value put in all diagonals of eliminated rows
6616 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6617 - b    - optional vector of right hand side, that will be adjusted by provided solution
6618 
6619   Level: intermediate
6620 
6621   Notes:
6622   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6623   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6624 
6625   See `MatZeroRowsColumns()` for details on how this routine operates.
6626 
6627 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6628           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6629 @*/
6630 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6631 {
6632   PetscInt        numRows;
6633   const PetscInt *rows;
6634 
6635   PetscFunctionBegin;
6636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6637   PetscValidType(mat, 1);
6638   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6641   MatCheckPreallocated(mat, 1);
6642 
6643   PetscCall(ISGetLocalSize(is, &numRows));
6644   PetscCall(ISGetIndices(is, &rows));
6645   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6646   PetscCall(ISRestoreIndices(is, &rows));
6647   PetscFunctionReturn(PETSC_SUCCESS);
6648 }
6649 
6650 /*@C
6651   MatGetSize - Returns the numbers of rows and columns in a matrix.
6652 
6653   Not Collective
6654 
6655   Input Parameter:
6656 . mat - the matrix
6657 
6658   Output Parameters:
6659 + m - the number of global rows
6660 - n - the number of global columns
6661 
6662   Level: beginner
6663 
6664   Note:
6665   Both output parameters can be `NULL` on input.
6666 
6667 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6668 @*/
6669 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6670 {
6671   PetscFunctionBegin;
6672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6673   if (m) *m = mat->rmap->N;
6674   if (n) *n = mat->cmap->N;
6675   PetscFunctionReturn(PETSC_SUCCESS);
6676 }
6677 
6678 /*@C
6679   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6680   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6681 
6682   Not Collective
6683 
6684   Input Parameter:
6685 . mat - the matrix
6686 
6687   Output Parameters:
6688 + m - the number of local rows, use `NULL` to not obtain this value
6689 - n - the number of local columns, use `NULL` to not obtain this value
6690 
6691   Level: beginner
6692 
6693 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6694 @*/
6695 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6696 {
6697   PetscFunctionBegin;
6698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6699   if (m) PetscAssertPointer(m, 2);
6700   if (n) PetscAssertPointer(n, 3);
6701   if (m) *m = mat->rmap->n;
6702   if (n) *n = mat->cmap->n;
6703   PetscFunctionReturn(PETSC_SUCCESS);
6704 }
6705 
6706 /*@C
6707   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6708   vector one multiplies this matrix by that are owned by this processor.
6709 
6710   Not Collective, unless matrix has not been allocated, then collective
6711 
6712   Input Parameter:
6713 . mat - the matrix
6714 
6715   Output Parameters:
6716 + m - the global index of the first local column, use `NULL` to not obtain this value
6717 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6718 
6719   Level: developer
6720 
6721   Note:
6722   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6723   Layouts](sec_matlayout) for details on matrix layouts.
6724 
6725 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6726 @*/
6727 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6728 {
6729   PetscFunctionBegin;
6730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6731   PetscValidType(mat, 1);
6732   if (m) PetscAssertPointer(m, 2);
6733   if (n) PetscAssertPointer(n, 3);
6734   MatCheckPreallocated(mat, 1);
6735   if (m) *m = mat->cmap->rstart;
6736   if (n) *n = mat->cmap->rend;
6737   PetscFunctionReturn(PETSC_SUCCESS);
6738 }
6739 
6740 /*@C
6741   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6742   this MPI process.
6743 
6744   Not Collective
6745 
6746   Input Parameter:
6747 . mat - the matrix
6748 
6749   Output Parameters:
6750 + m - the global index of the first local row, use `NULL` to not obtain this value
6751 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6752 
6753   Level: beginner
6754 
6755   Note:
6756   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6757   would contain the result of a matrix vector product with this matrix. See [Matrix
6758   Layouts](sec_matlayout) for details on matrix layouts.
6759 
6760 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6761           `PetscLayout`
6762 @*/
6763 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6764 {
6765   PetscFunctionBegin;
6766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6767   PetscValidType(mat, 1);
6768   if (m) PetscAssertPointer(m, 2);
6769   if (n) PetscAssertPointer(n, 3);
6770   MatCheckPreallocated(mat, 1);
6771   if (m) *m = mat->rmap->rstart;
6772   if (n) *n = mat->rmap->rend;
6773   PetscFunctionReturn(PETSC_SUCCESS);
6774 }
6775 
6776 /*@C
6777   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6778   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6779 
6780   Not Collective, unless matrix has not been allocated
6781 
6782   Input Parameter:
6783 . mat - the matrix
6784 
6785   Output Parameter:
6786 . ranges - start of each processors portion plus one more than the total length at the end
6787 
6788   Level: beginner
6789 
6790   Note:
6791   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6792   would contain the result of a matrix vector product with this matrix. See [Matrix
6793   Layouts](sec_matlayout) for details on matrix layouts.
6794 
6795 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6796 @*/
6797 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6798 {
6799   PetscFunctionBegin;
6800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6801   PetscValidType(mat, 1);
6802   MatCheckPreallocated(mat, 1);
6803   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6804   PetscFunctionReturn(PETSC_SUCCESS);
6805 }
6806 
6807 /*@C
6808   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6809   vector one multiplies this vector by that are owned by each processor.
6810 
6811   Not Collective, unless matrix has not been allocated
6812 
6813   Input Parameter:
6814 . mat - the matrix
6815 
6816   Output Parameter:
6817 . ranges - start of each processors portion plus one more than the total length at the end
6818 
6819   Level: beginner
6820 
6821   Note:
6822   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6823   Layouts](sec_matlayout) for details on matrix layouts.
6824 
6825 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6826 @*/
6827 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6828 {
6829   PetscFunctionBegin;
6830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6831   PetscValidType(mat, 1);
6832   MatCheckPreallocated(mat, 1);
6833   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6834   PetscFunctionReturn(PETSC_SUCCESS);
6835 }
6836 
6837 /*@C
6838   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6839 
6840   Not Collective
6841 
6842   Input Parameter:
6843 . A - matrix
6844 
6845   Output Parameters:
6846 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6847 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6848 
6849   Level: intermediate
6850 
6851   Note:
6852   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6853   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6854   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6855   details on matrix layouts.
6856 
6857 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6858 @*/
6859 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6860 {
6861   PetscErrorCode (*f)(Mat, IS *, IS *);
6862 
6863   PetscFunctionBegin;
6864   MatCheckPreallocated(A, 1);
6865   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6866   if (f) {
6867     PetscCall((*f)(A, rows, cols));
6868   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6869     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6870     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6871   }
6872   PetscFunctionReturn(PETSC_SUCCESS);
6873 }
6874 
6875 /*@C
6876   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6877   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6878   to complete the factorization.
6879 
6880   Collective
6881 
6882   Input Parameters:
6883 + fact - the factorized matrix obtained with `MatGetFactor()`
6884 . mat  - the matrix
6885 . row  - row permutation
6886 . col  - column permutation
6887 - info - structure containing
6888 .vb
6889       levels - number of levels of fill.
6890       expected fill - as ratio of original fill.
6891       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6892                 missing diagonal entries)
6893 .ve
6894 
6895   Level: developer
6896 
6897   Notes:
6898   See [Matrix Factorization](sec_matfactor) for additional information.
6899 
6900   Most users should employ the `KSP` interface for linear solvers
6901   instead of working directly with matrix algebra routines such as this.
6902   See, e.g., `KSPCreate()`.
6903 
6904   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6905 
6906   Developer Note:
6907   The Fortran interface is not autogenerated as the
6908   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6909 
6910 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6911           `MatGetOrdering()`, `MatFactorInfo`
6912 @*/
6913 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6914 {
6915   PetscFunctionBegin;
6916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6917   PetscValidType(mat, 2);
6918   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6919   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6920   PetscAssertPointer(info, 5);
6921   PetscAssertPointer(fact, 1);
6922   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6923   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6924   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6925   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6926   MatCheckPreallocated(mat, 2);
6927 
6928   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6929   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6930   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6931   PetscFunctionReturn(PETSC_SUCCESS);
6932 }
6933 
6934 /*@C
6935   MatICCFactorSymbolic - Performs symbolic incomplete
6936   Cholesky factorization for a symmetric matrix.  Use
6937   `MatCholeskyFactorNumeric()` to complete the factorization.
6938 
6939   Collective
6940 
6941   Input Parameters:
6942 + fact - the factorized matrix obtained with `MatGetFactor()`
6943 . mat  - the matrix to be factored
6944 . perm - row and column permutation
6945 - info - structure containing
6946 .vb
6947       levels - number of levels of fill.
6948       expected fill - as ratio of original fill.
6949 .ve
6950 
6951   Level: developer
6952 
6953   Notes:
6954   Most users should employ the `KSP` interface for linear solvers
6955   instead of working directly with matrix algebra routines such as this.
6956   See, e.g., `KSPCreate()`.
6957 
6958   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
6959 
6960   Developer Note:
6961   The Fortran interface is not autogenerated as the
6962   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6963 
6964 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6965 @*/
6966 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6967 {
6968   PetscFunctionBegin;
6969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6970   PetscValidType(mat, 2);
6971   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6972   PetscAssertPointer(info, 4);
6973   PetscAssertPointer(fact, 1);
6974   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6975   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6976   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6977   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6978   MatCheckPreallocated(mat, 2);
6979 
6980   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6981   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6982   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6983   PetscFunctionReturn(PETSC_SUCCESS);
6984 }
6985 
6986 /*@C
6987   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6988   points to an array of valid matrices, they may be reused to store the new
6989   submatrices.
6990 
6991   Collective
6992 
6993   Input Parameters:
6994 + mat   - the matrix
6995 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
6996 . irow  - index set of rows to extract
6997 . icol  - index set of columns to extract
6998 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6999 
7000   Output Parameter:
7001 . submat - the array of submatrices
7002 
7003   Level: advanced
7004 
7005   Notes:
7006   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7007   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7008   to extract a parallel submatrix.
7009 
7010   Some matrix types place restrictions on the row and column
7011   indices, such as that they be sorted or that they be equal to each other.
7012 
7013   The index sets may not have duplicate entries.
7014 
7015   When extracting submatrices from a parallel matrix, each processor can
7016   form a different submatrix by setting the rows and columns of its
7017   individual index sets according to the local submatrix desired.
7018 
7019   When finished using the submatrices, the user should destroy
7020   them with `MatDestroySubMatrices()`.
7021 
7022   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7023   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7024 
7025   This routine creates the matrices in submat; you should NOT create them before
7026   calling it. It also allocates the array of matrix pointers submat.
7027 
7028   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7029   request one row/column in a block, they must request all rows/columns that are in
7030   that block. For example, if the block size is 2 you cannot request just row 0 and
7031   column 0.
7032 
7033   Fortran Note:
7034   The Fortran interface is slightly different from that given below; it
7035   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7036 
7037 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7038 @*/
7039 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7040 {
7041   PetscInt  i;
7042   PetscBool eq;
7043 
7044   PetscFunctionBegin;
7045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7046   PetscValidType(mat, 1);
7047   if (n) {
7048     PetscAssertPointer(irow, 3);
7049     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7050     PetscAssertPointer(icol, 4);
7051     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7052   }
7053   PetscAssertPointer(submat, 6);
7054   if (n && scall == MAT_REUSE_MATRIX) {
7055     PetscAssertPointer(*submat, 6);
7056     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7057   }
7058   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7059   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7060   MatCheckPreallocated(mat, 1);
7061   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7062   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7063   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7064   for (i = 0; i < n; i++) {
7065     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7066     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7067     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7068 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7069     if (mat->boundtocpu && mat->bindingpropagates) {
7070       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7071       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7072     }
7073 #endif
7074   }
7075   PetscFunctionReturn(PETSC_SUCCESS);
7076 }
7077 
7078 /*@C
7079   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7080 
7081   Collective
7082 
7083   Input Parameters:
7084 + mat   - the matrix
7085 . n     - the number of submatrixes to be extracted
7086 . irow  - index set of rows to extract
7087 . icol  - index set of columns to extract
7088 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7089 
7090   Output Parameter:
7091 . submat - the array of submatrices
7092 
7093   Level: advanced
7094 
7095   Note:
7096   This is used by `PCGASM`
7097 
7098 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7099 @*/
7100 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7101 {
7102   PetscInt  i;
7103   PetscBool eq;
7104 
7105   PetscFunctionBegin;
7106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7107   PetscValidType(mat, 1);
7108   if (n) {
7109     PetscAssertPointer(irow, 3);
7110     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7111     PetscAssertPointer(icol, 4);
7112     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7113   }
7114   PetscAssertPointer(submat, 6);
7115   if (n && scall == MAT_REUSE_MATRIX) {
7116     PetscAssertPointer(*submat, 6);
7117     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7118   }
7119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7120   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7121   MatCheckPreallocated(mat, 1);
7122 
7123   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7124   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7125   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7126   for (i = 0; i < n; i++) {
7127     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7128     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7129   }
7130   PetscFunctionReturn(PETSC_SUCCESS);
7131 }
7132 
7133 /*@C
7134   MatDestroyMatrices - Destroys an array of matrices.
7135 
7136   Collective
7137 
7138   Input Parameters:
7139 + n   - the number of local matrices
7140 - mat - the matrices (this is a pointer to the array of matrices)
7141 
7142   Level: advanced
7143 
7144   Note:
7145   Frees not only the matrices, but also the array that contains the matrices
7146 
7147   Fortran Note:
7148   This does not free the array.
7149 
7150 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7151 @*/
7152 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7153 {
7154   PetscInt i;
7155 
7156   PetscFunctionBegin;
7157   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7158   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7159   PetscAssertPointer(mat, 2);
7160 
7161   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7162 
7163   /* memory is allocated even if n = 0 */
7164   PetscCall(PetscFree(*mat));
7165   PetscFunctionReturn(PETSC_SUCCESS);
7166 }
7167 
7168 /*@C
7169   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7170 
7171   Collective
7172 
7173   Input Parameters:
7174 + n   - the number of local matrices
7175 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7176                        sequence of `MatCreateSubMatrices()`)
7177 
7178   Level: advanced
7179 
7180   Note:
7181   Frees not only the matrices, but also the array that contains the matrices
7182 
7183   Fortran Note:
7184   This does not free the array.
7185 
7186 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7187 @*/
7188 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7189 {
7190   Mat mat0;
7191 
7192   PetscFunctionBegin;
7193   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7194   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7195   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7196   PetscAssertPointer(mat, 2);
7197 
7198   mat0 = (*mat)[0];
7199   if (mat0 && mat0->ops->destroysubmatrices) {
7200     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7201   } else {
7202     PetscCall(MatDestroyMatrices(n, mat));
7203   }
7204   PetscFunctionReturn(PETSC_SUCCESS);
7205 }
7206 
7207 /*@C
7208   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7209 
7210   Collective
7211 
7212   Input Parameter:
7213 . mat - the matrix
7214 
7215   Output Parameter:
7216 . matstruct - the sequential matrix with the nonzero structure of mat
7217 
7218   Level: developer
7219 
7220 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7221 @*/
7222 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7223 {
7224   PetscFunctionBegin;
7225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7226   PetscAssertPointer(matstruct, 2);
7227 
7228   PetscValidType(mat, 1);
7229   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7230   MatCheckPreallocated(mat, 1);
7231 
7232   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7233   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7234   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7235   PetscFunctionReturn(PETSC_SUCCESS);
7236 }
7237 
7238 /*@C
7239   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7240 
7241   Collective
7242 
7243   Input Parameter:
7244 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7245                        sequence of `MatGetSeqNonzeroStructure()`)
7246 
7247   Level: advanced
7248 
7249   Note:
7250   Frees not only the matrices, but also the array that contains the matrices
7251 
7252 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7253 @*/
7254 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7255 {
7256   PetscFunctionBegin;
7257   PetscAssertPointer(mat, 1);
7258   PetscCall(MatDestroy(mat));
7259   PetscFunctionReturn(PETSC_SUCCESS);
7260 }
7261 
7262 /*@
7263   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7264   replaces the index sets by larger ones that represent submatrices with
7265   additional overlap.
7266 
7267   Collective
7268 
7269   Input Parameters:
7270 + mat - the matrix
7271 . n   - the number of index sets
7272 . is  - the array of index sets (these index sets will changed during the call)
7273 - ov  - the additional overlap requested
7274 
7275   Options Database Key:
7276 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7277 
7278   Level: developer
7279 
7280   Note:
7281   The computed overlap preserves the matrix block sizes when the blocks are square.
7282   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7283   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7284 
7285 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7286 @*/
7287 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7288 {
7289   PetscInt i, bs, cbs;
7290 
7291   PetscFunctionBegin;
7292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7293   PetscValidType(mat, 1);
7294   PetscValidLogicalCollectiveInt(mat, n, 2);
7295   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7296   if (n) {
7297     PetscAssertPointer(is, 3);
7298     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7299   }
7300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7301   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7302   MatCheckPreallocated(mat, 1);
7303 
7304   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7305   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7306   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7307   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7308   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7309   if (bs == cbs) {
7310     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7311   }
7312   PetscFunctionReturn(PETSC_SUCCESS);
7313 }
7314 
7315 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7316 
7317 /*@
7318   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7319   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7320   additional overlap.
7321 
7322   Collective
7323 
7324   Input Parameters:
7325 + mat - the matrix
7326 . n   - the number of index sets
7327 . is  - the array of index sets (these index sets will changed during the call)
7328 - ov  - the additional overlap requested
7329 
7330   `   Options Database Key:
7331 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7332 
7333   Level: developer
7334 
7335 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7336 @*/
7337 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7338 {
7339   PetscInt i;
7340 
7341   PetscFunctionBegin;
7342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7343   PetscValidType(mat, 1);
7344   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7345   if (n) {
7346     PetscAssertPointer(is, 3);
7347     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7348   }
7349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7350   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7351   MatCheckPreallocated(mat, 1);
7352   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7353   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7354   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7355   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7356   PetscFunctionReturn(PETSC_SUCCESS);
7357 }
7358 
7359 /*@
7360   MatGetBlockSize - Returns the matrix block size.
7361 
7362   Not Collective
7363 
7364   Input Parameter:
7365 . mat - the matrix
7366 
7367   Output Parameter:
7368 . bs - block size
7369 
7370   Level: intermediate
7371 
7372   Notes:
7373   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7374 
7375   If the block size has not been set yet this routine returns 1.
7376 
7377 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7378 @*/
7379 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7380 {
7381   PetscFunctionBegin;
7382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7383   PetscAssertPointer(bs, 2);
7384   *bs = PetscAbs(mat->rmap->bs);
7385   PetscFunctionReturn(PETSC_SUCCESS);
7386 }
7387 
7388 /*@
7389   MatGetBlockSizes - Returns the matrix block row and column sizes.
7390 
7391   Not Collective
7392 
7393   Input Parameter:
7394 . mat - the matrix
7395 
7396   Output Parameters:
7397 + rbs - row block size
7398 - cbs - column block size
7399 
7400   Level: intermediate
7401 
7402   Notes:
7403   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7404   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7405 
7406   If a block size has not been set yet this routine returns 1.
7407 
7408 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7409 @*/
7410 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7411 {
7412   PetscFunctionBegin;
7413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7414   if (rbs) PetscAssertPointer(rbs, 2);
7415   if (cbs) PetscAssertPointer(cbs, 3);
7416   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7417   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7418   PetscFunctionReturn(PETSC_SUCCESS);
7419 }
7420 
7421 /*@
7422   MatSetBlockSize - Sets the matrix block size.
7423 
7424   Logically Collective
7425 
7426   Input Parameters:
7427 + mat - the matrix
7428 - bs  - block size
7429 
7430   Level: intermediate
7431 
7432   Notes:
7433   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7434   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7435 
7436   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7437   is compatible with the matrix local sizes.
7438 
7439 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7440 @*/
7441 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7442 {
7443   PetscFunctionBegin;
7444   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7445   PetscValidLogicalCollectiveInt(mat, bs, 2);
7446   PetscCall(MatSetBlockSizes(mat, bs, bs));
7447   PetscFunctionReturn(PETSC_SUCCESS);
7448 }
7449 
7450 typedef struct {
7451   PetscInt         n;
7452   IS              *is;
7453   Mat             *mat;
7454   PetscObjectState nonzerostate;
7455   Mat              C;
7456 } EnvelopeData;
7457 
7458 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7459 {
7460   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7461   PetscCall(PetscFree(edata->is));
7462   PetscCall(PetscFree(edata));
7463   return PETSC_SUCCESS;
7464 }
7465 
7466 /*@
7467   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7468   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7469 
7470   Collective
7471 
7472   Input Parameter:
7473 . mat - the matrix
7474 
7475   Level: intermediate
7476 
7477   Notes:
7478   There can be zeros within the blocks
7479 
7480   The blocks can overlap between processes, including laying on more than two processes
7481 
7482 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7483 @*/
7484 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7485 {
7486   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7487   PetscInt          *diag, *odiag, sc;
7488   VecScatter         scatter;
7489   PetscScalar       *seqv;
7490   const PetscScalar *parv;
7491   const PetscInt    *ia, *ja;
7492   PetscBool          set, flag, done;
7493   Mat                AA = mat, A;
7494   MPI_Comm           comm;
7495   PetscMPIInt        rank, size, tag;
7496   MPI_Status         status;
7497   PetscContainer     container;
7498   EnvelopeData      *edata;
7499   Vec                seq, par;
7500   IS                 isglobal;
7501 
7502   PetscFunctionBegin;
7503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7504   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7505   if (!set || !flag) {
7506     /* TODO: only needs nonzero structure of transpose */
7507     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7508     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7509   }
7510   PetscCall(MatAIJGetLocalMat(AA, &A));
7511   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7512   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7513 
7514   PetscCall(MatGetLocalSize(mat, &n, NULL));
7515   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7516   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7517   PetscCallMPI(MPI_Comm_size(comm, &size));
7518   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7519 
7520   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7521 
7522   if (rank > 0) {
7523     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7524     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7525   }
7526   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7527   for (i = 0; i < n; i++) {
7528     env = PetscMax(env, ja[ia[i + 1] - 1]);
7529     II  = rstart + i;
7530     if (env == II) {
7531       starts[lblocks]  = tbs;
7532       sizes[lblocks++] = 1 + II - tbs;
7533       tbs              = 1 + II;
7534     }
7535   }
7536   if (rank < size - 1) {
7537     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7538     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7539   }
7540 
7541   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7542   if (!set || !flag) PetscCall(MatDestroy(&AA));
7543   PetscCall(MatDestroy(&A));
7544 
7545   PetscCall(PetscNew(&edata));
7546   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7547   edata->n = lblocks;
7548   /* create IS needed for extracting blocks from the original matrix */
7549   PetscCall(PetscMalloc1(lblocks, &edata->is));
7550   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7551 
7552   /* Create the resulting inverse matrix structure with preallocation information */
7553   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7554   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7555   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7556   PetscCall(MatSetType(edata->C, MATAIJ));
7557 
7558   /* Communicate the start and end of each row, from each block to the correct rank */
7559   /* TODO: Use PetscSF instead of VecScatter */
7560   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7561   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7562   PetscCall(VecGetArrayWrite(seq, &seqv));
7563   for (PetscInt i = 0; i < lblocks; i++) {
7564     for (PetscInt j = 0; j < sizes[i]; j++) {
7565       seqv[cnt]     = starts[i];
7566       seqv[cnt + 1] = starts[i] + sizes[i];
7567       cnt += 2;
7568     }
7569   }
7570   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7571   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7572   sc -= cnt;
7573   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7574   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7575   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7576   PetscCall(ISDestroy(&isglobal));
7577   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7578   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7579   PetscCall(VecScatterDestroy(&scatter));
7580   PetscCall(VecDestroy(&seq));
7581   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7582   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7583   PetscCall(VecGetArrayRead(par, &parv));
7584   cnt = 0;
7585   PetscCall(MatGetSize(mat, NULL, &n));
7586   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7587     PetscInt start, end, d = 0, od = 0;
7588 
7589     start = (PetscInt)PetscRealPart(parv[cnt]);
7590     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7591     cnt += 2;
7592 
7593     if (start < cstart) {
7594       od += cstart - start + n - cend;
7595       d += cend - cstart;
7596     } else if (start < cend) {
7597       od += n - cend;
7598       d += cend - start;
7599     } else od += n - start;
7600     if (end <= cstart) {
7601       od -= cstart - end + n - cend;
7602       d -= cend - cstart;
7603     } else if (end < cend) {
7604       od -= n - cend;
7605       d -= cend - end;
7606     } else od -= n - end;
7607 
7608     odiag[i] = od;
7609     diag[i]  = d;
7610   }
7611   PetscCall(VecRestoreArrayRead(par, &parv));
7612   PetscCall(VecDestroy(&par));
7613   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7614   PetscCall(PetscFree2(diag, odiag));
7615   PetscCall(PetscFree2(sizes, starts));
7616 
7617   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7618   PetscCall(PetscContainerSetPointer(container, edata));
7619   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7620   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7621   PetscCall(PetscObjectDereference((PetscObject)container));
7622   PetscFunctionReturn(PETSC_SUCCESS);
7623 }
7624 
7625 /*@
7626   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7627 
7628   Collective
7629 
7630   Input Parameters:
7631 + A     - the matrix
7632 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7633 
7634   Output Parameter:
7635 . C - matrix with inverted block diagonal of `A`
7636 
7637   Level: advanced
7638 
7639   Note:
7640   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7641 
7642 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7643 @*/
7644 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7645 {
7646   PetscContainer   container;
7647   EnvelopeData    *edata;
7648   PetscObjectState nonzerostate;
7649 
7650   PetscFunctionBegin;
7651   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7652   if (!container) {
7653     PetscCall(MatComputeVariableBlockEnvelope(A));
7654     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7655   }
7656   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7657   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7658   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7659   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7660 
7661   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7662   *C = edata->C;
7663 
7664   for (PetscInt i = 0; i < edata->n; i++) {
7665     Mat          D;
7666     PetscScalar *dvalues;
7667 
7668     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7669     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7670     PetscCall(MatSeqDenseInvert(D));
7671     PetscCall(MatDenseGetArray(D, &dvalues));
7672     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7673     PetscCall(MatDestroy(&D));
7674   }
7675   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7676   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7677   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7678   PetscFunctionReturn(PETSC_SUCCESS);
7679 }
7680 
7681 /*@
7682   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7683 
7684   Logically Collective
7685 
7686   Input Parameters:
7687 + mat     - the matrix
7688 . nblocks - the number of blocks on this process, each block can only exist on a single process
7689 - bsizes  - the block sizes
7690 
7691   Level: intermediate
7692 
7693   Notes:
7694   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7695 
7696   Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes.
7697 
7698 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7699           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7700 @*/
7701 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7702 {
7703   PetscInt i, ncnt = 0, nlocal;
7704 
7705   PetscFunctionBegin;
7706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7707   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7708   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7709   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7710   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);
7711   PetscCall(PetscFree(mat->bsizes));
7712   mat->nblocks = nblocks;
7713   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7714   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7715   PetscFunctionReturn(PETSC_SUCCESS);
7716 }
7717 
7718 /*@C
7719   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7720 
7721   Logically Collective; No Fortran Support
7722 
7723   Input Parameter:
7724 . mat - the matrix
7725 
7726   Output Parameters:
7727 + nblocks - the number of blocks on this process
7728 - bsizes  - the block sizes
7729 
7730   Level: intermediate
7731 
7732 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7733 @*/
7734 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7735 {
7736   PetscFunctionBegin;
7737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7738   *nblocks = mat->nblocks;
7739   *bsizes  = mat->bsizes;
7740   PetscFunctionReturn(PETSC_SUCCESS);
7741 }
7742 
7743 /*@
7744   MatSetBlockSizes - Sets the matrix block row and column sizes.
7745 
7746   Logically Collective
7747 
7748   Input Parameters:
7749 + mat - the matrix
7750 . rbs - row block size
7751 - cbs - column block size
7752 
7753   Level: intermediate
7754 
7755   Notes:
7756   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7757   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7758   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7759 
7760   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7761   are compatible with the matrix local sizes.
7762 
7763   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7764 
7765 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7766 @*/
7767 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7768 {
7769   PetscFunctionBegin;
7770   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7771   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7772   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7773   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7774   if (mat->rmap->refcnt) {
7775     ISLocalToGlobalMapping l2g  = NULL;
7776     PetscLayout            nmap = NULL;
7777 
7778     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7779     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7780     PetscCall(PetscLayoutDestroy(&mat->rmap));
7781     mat->rmap          = nmap;
7782     mat->rmap->mapping = l2g;
7783   }
7784   if (mat->cmap->refcnt) {
7785     ISLocalToGlobalMapping l2g  = NULL;
7786     PetscLayout            nmap = NULL;
7787 
7788     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7789     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7790     PetscCall(PetscLayoutDestroy(&mat->cmap));
7791     mat->cmap          = nmap;
7792     mat->cmap->mapping = l2g;
7793   }
7794   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7795   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7796   PetscFunctionReturn(PETSC_SUCCESS);
7797 }
7798 
7799 /*@
7800   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7801 
7802   Logically Collective
7803 
7804   Input Parameters:
7805 + mat     - the matrix
7806 . fromRow - matrix from which to copy row block size
7807 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7808 
7809   Level: developer
7810 
7811 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7812 @*/
7813 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7814 {
7815   PetscFunctionBegin;
7816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7817   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7818   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7819   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7820   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7821   PetscFunctionReturn(PETSC_SUCCESS);
7822 }
7823 
7824 /*@
7825   MatResidual - Default routine to calculate the residual r = b - Ax
7826 
7827   Collective
7828 
7829   Input Parameters:
7830 + mat - the matrix
7831 . b   - the right-hand-side
7832 - x   - the approximate solution
7833 
7834   Output Parameter:
7835 . r - location to store the residual
7836 
7837   Level: developer
7838 
7839 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7840 @*/
7841 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7842 {
7843   PetscFunctionBegin;
7844   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7845   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7846   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7847   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7848   PetscValidType(mat, 1);
7849   MatCheckPreallocated(mat, 1);
7850   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7851   if (!mat->ops->residual) {
7852     PetscCall(MatMult(mat, x, r));
7853     PetscCall(VecAYPX(r, -1.0, b));
7854   } else {
7855     PetscUseTypeMethod(mat, residual, b, x, r);
7856   }
7857   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7858   PetscFunctionReturn(PETSC_SUCCESS);
7859 }
7860 
7861 /*MC
7862     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7863 
7864     Synopsis:
7865     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7866 
7867     Not Collective
7868 
7869     Input Parameters:
7870 +   A - the matrix
7871 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7872 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7873 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7874                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7875                  always used.
7876 
7877     Output Parameters:
7878 +   n - number of local rows in the (possibly compressed) matrix
7879 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7880 .   ja - the column indices
7881 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7882            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7883 
7884     Level: developer
7885 
7886     Note:
7887     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7888 
7889 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7890 M*/
7891 
7892 /*MC
7893     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7894 
7895     Synopsis:
7896     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7897 
7898     Not Collective
7899 
7900     Input Parameters:
7901 +   A - the  matrix
7902 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7903 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7904     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7905                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7906                  always used.
7907 .   n - number of local rows in the (possibly compressed) matrix
7908 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7909 .   ja - the column indices
7910 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7911            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7912 
7913     Level: developer
7914 
7915 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7916 M*/
7917 
7918 /*@C
7919   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7920 
7921   Collective
7922 
7923   Input Parameters:
7924 + mat             - the matrix
7925 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7926 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7927 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7928                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7929                  always used.
7930 
7931   Output Parameters:
7932 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7933 . 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
7934 . ja   - the column indices, use `NULL` if not needed
7935 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7936            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7937 
7938   Level: developer
7939 
7940   Notes:
7941   You CANNOT change any of the ia[] or ja[] values.
7942 
7943   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7944 
7945   Fortran Notes:
7946   Use
7947 .vb
7948     PetscInt, pointer :: ia(:),ja(:)
7949     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7950     ! Access the ith and jth entries via ia(i) and ja(j)
7951 .ve
7952 
7953   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7954 
7955 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7956 @*/
7957 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7958 {
7959   PetscFunctionBegin;
7960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7961   PetscValidType(mat, 1);
7962   if (n) PetscAssertPointer(n, 5);
7963   if (ia) PetscAssertPointer(ia, 6);
7964   if (ja) PetscAssertPointer(ja, 7);
7965   if (done) PetscAssertPointer(done, 8);
7966   MatCheckPreallocated(mat, 1);
7967   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7968   else {
7969     if (done) *done = PETSC_TRUE;
7970     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7971     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7972     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7973   }
7974   PetscFunctionReturn(PETSC_SUCCESS);
7975 }
7976 
7977 /*@C
7978   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7979 
7980   Collective
7981 
7982   Input Parameters:
7983 + mat             - the matrix
7984 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
7985 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7986                 symmetrized
7987 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7988                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7989                  always used.
7990 . n               - number of columns in the (possibly compressed) matrix
7991 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7992 - ja              - the row indices
7993 
7994   Output Parameter:
7995 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7996 
7997   Level: developer
7998 
7999 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8000 @*/
8001 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8002 {
8003   PetscFunctionBegin;
8004   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8005   PetscValidType(mat, 1);
8006   PetscAssertPointer(n, 5);
8007   if (ia) PetscAssertPointer(ia, 6);
8008   if (ja) PetscAssertPointer(ja, 7);
8009   PetscAssertPointer(done, 8);
8010   MatCheckPreallocated(mat, 1);
8011   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8012   else {
8013     *done = PETSC_TRUE;
8014     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8015   }
8016   PetscFunctionReturn(PETSC_SUCCESS);
8017 }
8018 
8019 /*@C
8020   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8021 
8022   Collective
8023 
8024   Input Parameters:
8025 + mat             - the matrix
8026 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8027 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8028 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8029                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8030                  always used.
8031 . n               - size of (possibly compressed) matrix
8032 . ia              - the row pointers
8033 - ja              - the column indices
8034 
8035   Output Parameter:
8036 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8037 
8038   Level: developer
8039 
8040   Note:
8041   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8042   us of the array after it has been restored. If you pass `NULL`, it will
8043   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8044 
8045   Fortran Note:
8046   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8047 
8048 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8049 @*/
8050 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8051 {
8052   PetscFunctionBegin;
8053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8054   PetscValidType(mat, 1);
8055   if (ia) PetscAssertPointer(ia, 6);
8056   if (ja) PetscAssertPointer(ja, 7);
8057   if (done) PetscAssertPointer(done, 8);
8058   MatCheckPreallocated(mat, 1);
8059 
8060   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8061   else {
8062     if (done) *done = PETSC_TRUE;
8063     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8064     if (n) *n = 0;
8065     if (ia) *ia = NULL;
8066     if (ja) *ja = NULL;
8067   }
8068   PetscFunctionReturn(PETSC_SUCCESS);
8069 }
8070 
8071 /*@C
8072   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8073 
8074   Collective
8075 
8076   Input Parameters:
8077 + mat             - the matrix
8078 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8079 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8080 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8081                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8082                  always used.
8083 
8084   Output Parameters:
8085 + n    - size of (possibly compressed) matrix
8086 . ia   - the column pointers
8087 . ja   - the row indices
8088 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8089 
8090   Level: developer
8091 
8092 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8093 @*/
8094 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8095 {
8096   PetscFunctionBegin;
8097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8098   PetscValidType(mat, 1);
8099   if (ia) PetscAssertPointer(ia, 6);
8100   if (ja) PetscAssertPointer(ja, 7);
8101   PetscAssertPointer(done, 8);
8102   MatCheckPreallocated(mat, 1);
8103 
8104   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8105   else {
8106     *done = PETSC_TRUE;
8107     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8108     if (n) *n = 0;
8109     if (ia) *ia = NULL;
8110     if (ja) *ja = NULL;
8111   }
8112   PetscFunctionReturn(PETSC_SUCCESS);
8113 }
8114 
8115 /*@C
8116   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8117   `MatGetColumnIJ()`.
8118 
8119   Collective
8120 
8121   Input Parameters:
8122 + mat        - the matrix
8123 . ncolors    - maximum color value
8124 . n          - number of entries in colorarray
8125 - colorarray - array indicating color for each column
8126 
8127   Output Parameter:
8128 . iscoloring - coloring generated using colorarray information
8129 
8130   Level: developer
8131 
8132 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8133 @*/
8134 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8135 {
8136   PetscFunctionBegin;
8137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8138   PetscValidType(mat, 1);
8139   PetscAssertPointer(colorarray, 4);
8140   PetscAssertPointer(iscoloring, 5);
8141   MatCheckPreallocated(mat, 1);
8142 
8143   if (!mat->ops->coloringpatch) {
8144     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8145   } else {
8146     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8147   }
8148   PetscFunctionReturn(PETSC_SUCCESS);
8149 }
8150 
8151 /*@
8152   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8153 
8154   Logically Collective
8155 
8156   Input Parameter:
8157 . mat - the factored matrix to be reset
8158 
8159   Level: developer
8160 
8161   Notes:
8162   This routine should be used only with factored matrices formed by in-place
8163   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8164   format).  This option can save memory, for example, when solving nonlinear
8165   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8166   ILU(0) preconditioner.
8167 
8168   One can specify in-place ILU(0) factorization by calling
8169 .vb
8170      PCType(pc,PCILU);
8171      PCFactorSeUseInPlace(pc);
8172 .ve
8173   or by using the options -pc_type ilu -pc_factor_in_place
8174 
8175   In-place factorization ILU(0) can also be used as a local
8176   solver for the blocks within the block Jacobi or additive Schwarz
8177   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8178   for details on setting local solver options.
8179 
8180   Most users should employ the `KSP` interface for linear solvers
8181   instead of working directly with matrix algebra routines such as this.
8182   See, e.g., `KSPCreate()`.
8183 
8184 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8185 @*/
8186 PetscErrorCode MatSetUnfactored(Mat mat)
8187 {
8188   PetscFunctionBegin;
8189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8190   PetscValidType(mat, 1);
8191   MatCheckPreallocated(mat, 1);
8192   mat->factortype = MAT_FACTOR_NONE;
8193   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8194   PetscUseTypeMethod(mat, setunfactored);
8195   PetscFunctionReturn(PETSC_SUCCESS);
8196 }
8197 
8198 /*MC
8199     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8200 
8201     Synopsis:
8202     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8203 
8204     Not Collective
8205 
8206     Input Parameter:
8207 .   x - matrix
8208 
8209     Output Parameters:
8210 +   xx_v - the Fortran pointer to the array
8211 -   ierr - error code
8212 
8213     Example of Usage:
8214 .vb
8215       PetscScalar, pointer xx_v(:,:)
8216       ....
8217       call MatDenseGetArrayF90(x,xx_v,ierr)
8218       a = xx_v(3)
8219       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8220 .ve
8221 
8222     Level: advanced
8223 
8224 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8225 M*/
8226 
8227 /*MC
8228     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8229     accessed with `MatDenseGetArrayF90()`.
8230 
8231     Synopsis:
8232     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8233 
8234     Not Collective
8235 
8236     Input Parameters:
8237 +   x - matrix
8238 -   xx_v - the Fortran90 pointer to the array
8239 
8240     Output Parameter:
8241 .   ierr - error code
8242 
8243     Example of Usage:
8244 .vb
8245        PetscScalar, pointer xx_v(:,:)
8246        ....
8247        call MatDenseGetArrayF90(x,xx_v,ierr)
8248        a = xx_v(3)
8249        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8250 .ve
8251 
8252     Level: advanced
8253 
8254 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8255 M*/
8256 
8257 /*MC
8258     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8259 
8260     Synopsis:
8261     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8262 
8263     Not Collective
8264 
8265     Input Parameter:
8266 .   x - matrix
8267 
8268     Output Parameters:
8269 +   xx_v - the Fortran pointer to the array
8270 -   ierr - error code
8271 
8272     Example of Usage:
8273 .vb
8274       PetscScalar, pointer xx_v(:)
8275       ....
8276       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8277       a = xx_v(3)
8278       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8279 .ve
8280 
8281     Level: advanced
8282 
8283 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8284 M*/
8285 
8286 /*MC
8287     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8288     accessed with `MatSeqAIJGetArrayF90()`.
8289 
8290     Synopsis:
8291     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8292 
8293     Not Collective
8294 
8295     Input Parameters:
8296 +   x - matrix
8297 -   xx_v - the Fortran90 pointer to the array
8298 
8299     Output Parameter:
8300 .   ierr - error code
8301 
8302     Example of Usage:
8303 .vb
8304        PetscScalar, pointer xx_v(:)
8305        ....
8306        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8307        a = xx_v(3)
8308        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8309 .ve
8310 
8311     Level: advanced
8312 
8313 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8314 M*/
8315 
8316 /*@
8317   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8318   as the original matrix.
8319 
8320   Collective
8321 
8322   Input Parameters:
8323 + mat   - the original matrix
8324 . isrow - parallel `IS` containing the rows this processor should obtain
8325 . 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.
8326 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8327 
8328   Output Parameter:
8329 . newmat - the new submatrix, of the same type as the original matrix
8330 
8331   Level: advanced
8332 
8333   Notes:
8334   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8335 
8336   Some matrix types place restrictions on the row and column indices, such
8337   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;
8338   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8339 
8340   The index sets may not have duplicate entries.
8341 
8342   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8343   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8344   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8345   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8346   you are finished using it.
8347 
8348   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8349   the input matrix.
8350 
8351   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8352 
8353   Example usage:
8354   Consider the following 8x8 matrix with 34 non-zero values, that is
8355   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8356   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8357   as follows
8358 .vb
8359             1  2  0  |  0  3  0  |  0  4
8360     Proc0   0  5  6  |  7  0  0  |  8  0
8361             9  0 10  | 11  0  0  | 12  0
8362     -------------------------------------
8363            13  0 14  | 15 16 17  |  0  0
8364     Proc1   0 18  0  | 19 20 21  |  0  0
8365             0  0  0  | 22 23  0  | 24  0
8366     -------------------------------------
8367     Proc2  25 26 27  |  0  0 28  | 29  0
8368            30  0  0  | 31 32 33  |  0 34
8369 .ve
8370 
8371   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8372 
8373 .vb
8374             2  0  |  0  3  0  |  0
8375     Proc0   5  6  |  7  0  0  |  8
8376     -------------------------------
8377     Proc1  18  0  | 19 20 21  |  0
8378     -------------------------------
8379     Proc2  26 27  |  0  0 28  | 29
8380             0  0  | 31 32 33  |  0
8381 .ve
8382 
8383 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8384 @*/
8385 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8386 {
8387   PetscMPIInt size;
8388   Mat        *local;
8389   IS          iscoltmp;
8390   PetscBool   flg;
8391 
8392   PetscFunctionBegin;
8393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8394   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8395   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8396   PetscAssertPointer(newmat, 5);
8397   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8398   PetscValidType(mat, 1);
8399   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8400   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8401 
8402   MatCheckPreallocated(mat, 1);
8403   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8404 
8405   if (!iscol || isrow == iscol) {
8406     PetscBool   stride;
8407     PetscMPIInt grabentirematrix = 0, grab;
8408     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8409     if (stride) {
8410       PetscInt first, step, n, rstart, rend;
8411       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8412       if (step == 1) {
8413         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8414         if (rstart == first) {
8415           PetscCall(ISGetLocalSize(isrow, &n));
8416           if (n == rend - rstart) grabentirematrix = 1;
8417         }
8418       }
8419     }
8420     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8421     if (grab) {
8422       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8423       if (cll == MAT_INITIAL_MATRIX) {
8424         *newmat = mat;
8425         PetscCall(PetscObjectReference((PetscObject)mat));
8426       }
8427       PetscFunctionReturn(PETSC_SUCCESS);
8428     }
8429   }
8430 
8431   if (!iscol) {
8432     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8433   } else {
8434     iscoltmp = iscol;
8435   }
8436 
8437   /* if original matrix is on just one processor then use submatrix generated */
8438   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8439     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8440     goto setproperties;
8441   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8442     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8443     *newmat = *local;
8444     PetscCall(PetscFree(local));
8445     goto setproperties;
8446   } else if (!mat->ops->createsubmatrix) {
8447     /* Create a new matrix type that implements the operation using the full matrix */
8448     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8449     switch (cll) {
8450     case MAT_INITIAL_MATRIX:
8451       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8452       break;
8453     case MAT_REUSE_MATRIX:
8454       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8455       break;
8456     default:
8457       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8458     }
8459     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8460     goto setproperties;
8461   }
8462 
8463   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8464   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8465   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8466 
8467 setproperties:
8468   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8469   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8470   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8471   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8472   PetscFunctionReturn(PETSC_SUCCESS);
8473 }
8474 
8475 /*@
8476   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8477 
8478   Not Collective
8479 
8480   Input Parameters:
8481 + A - the matrix we wish to propagate options from
8482 - B - the matrix we wish to propagate options to
8483 
8484   Level: beginner
8485 
8486   Note:
8487   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8488 
8489 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8490 @*/
8491 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8492 {
8493   PetscFunctionBegin;
8494   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8495   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8496   B->symmetry_eternal            = A->symmetry_eternal;
8497   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8498   B->symmetric                   = A->symmetric;
8499   B->structurally_symmetric      = A->structurally_symmetric;
8500   B->spd                         = A->spd;
8501   B->hermitian                   = A->hermitian;
8502   PetscFunctionReturn(PETSC_SUCCESS);
8503 }
8504 
8505 /*@
8506   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8507   used during the assembly process to store values that belong to
8508   other processors.
8509 
8510   Not Collective
8511 
8512   Input Parameters:
8513 + mat   - the matrix
8514 . size  - the initial size of the stash.
8515 - bsize - the initial size of the block-stash(if used).
8516 
8517   Options Database Keys:
8518 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8519 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8520 
8521   Level: intermediate
8522 
8523   Notes:
8524   The block-stash is used for values set with `MatSetValuesBlocked()` while
8525   the stash is used for values set with `MatSetValues()`
8526 
8527   Run with the option -info and look for output of the form
8528   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8529   to determine the appropriate value, MM, to use for size and
8530   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8531   to determine the value, BMM to use for bsize
8532 
8533 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8534 @*/
8535 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8536 {
8537   PetscFunctionBegin;
8538   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8539   PetscValidType(mat, 1);
8540   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8541   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8542   PetscFunctionReturn(PETSC_SUCCESS);
8543 }
8544 
8545 /*@
8546   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8547   the matrix
8548 
8549   Neighbor-wise Collective
8550 
8551   Input Parameters:
8552 + A - the matrix
8553 . x - the vector to be multiplied by the interpolation operator
8554 - y - the vector to be added to the result
8555 
8556   Output Parameter:
8557 . w - the resulting vector
8558 
8559   Level: intermediate
8560 
8561   Notes:
8562   `w` may be the same vector as `y`.
8563 
8564   This allows one to use either the restriction or interpolation (its transpose)
8565   matrix to do the interpolation
8566 
8567 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8568 @*/
8569 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8570 {
8571   PetscInt M, N, Ny;
8572 
8573   PetscFunctionBegin;
8574   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8575   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8576   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8577   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8578   PetscCall(MatGetSize(A, &M, &N));
8579   PetscCall(VecGetSize(y, &Ny));
8580   if (M == Ny) {
8581     PetscCall(MatMultAdd(A, x, y, w));
8582   } else {
8583     PetscCall(MatMultTransposeAdd(A, x, y, w));
8584   }
8585   PetscFunctionReturn(PETSC_SUCCESS);
8586 }
8587 
8588 /*@
8589   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8590   the matrix
8591 
8592   Neighbor-wise Collective
8593 
8594   Input Parameters:
8595 + A - the matrix
8596 - x - the vector to be interpolated
8597 
8598   Output Parameter:
8599 . y - the resulting vector
8600 
8601   Level: intermediate
8602 
8603   Note:
8604   This allows one to use either the restriction or interpolation (its transpose)
8605   matrix to do the interpolation
8606 
8607 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8608 @*/
8609 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8610 {
8611   PetscInt M, N, Ny;
8612 
8613   PetscFunctionBegin;
8614   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8615   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8616   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8617   PetscCall(MatGetSize(A, &M, &N));
8618   PetscCall(VecGetSize(y, &Ny));
8619   if (M == Ny) {
8620     PetscCall(MatMult(A, x, y));
8621   } else {
8622     PetscCall(MatMultTranspose(A, x, y));
8623   }
8624   PetscFunctionReturn(PETSC_SUCCESS);
8625 }
8626 
8627 /*@
8628   MatRestrict - $y = A*x$ or $A^T*x$
8629 
8630   Neighbor-wise Collective
8631 
8632   Input Parameters:
8633 + A - the matrix
8634 - x - the vector to be restricted
8635 
8636   Output Parameter:
8637 . y - the resulting vector
8638 
8639   Level: intermediate
8640 
8641   Note:
8642   This allows one to use either the restriction or interpolation (its transpose)
8643   matrix to do the restriction
8644 
8645 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8646 @*/
8647 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8648 {
8649   PetscInt M, N, Ny;
8650 
8651   PetscFunctionBegin;
8652   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8653   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8654   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8655   PetscCall(MatGetSize(A, &M, &N));
8656   PetscCall(VecGetSize(y, &Ny));
8657   if (M == Ny) {
8658     PetscCall(MatMult(A, x, y));
8659   } else {
8660     PetscCall(MatMultTranspose(A, x, y));
8661   }
8662   PetscFunctionReturn(PETSC_SUCCESS);
8663 }
8664 
8665 /*@
8666   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8667 
8668   Neighbor-wise Collective
8669 
8670   Input Parameters:
8671 + A - the matrix
8672 . x - the input dense matrix to be multiplied
8673 - w - the input dense matrix to be added to the result
8674 
8675   Output Parameter:
8676 . y - the output dense matrix
8677 
8678   Level: intermediate
8679 
8680   Note:
8681   This allows one to use either the restriction or interpolation (its transpose)
8682   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8683   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8684 
8685 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8686 @*/
8687 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8688 {
8689   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8690   PetscBool trans = PETSC_TRUE;
8691   MatReuse  reuse = MAT_INITIAL_MATRIX;
8692 
8693   PetscFunctionBegin;
8694   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8695   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8696   PetscValidType(x, 2);
8697   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8698   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8699   PetscCall(MatGetSize(A, &M, &N));
8700   PetscCall(MatGetSize(x, &Mx, &Nx));
8701   if (N == Mx) trans = PETSC_FALSE;
8702   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);
8703   Mo = trans ? N : M;
8704   if (*y) {
8705     PetscCall(MatGetSize(*y, &My, &Ny));
8706     if (Mo == My && Nx == Ny) {
8707       reuse = MAT_REUSE_MATRIX;
8708     } else {
8709       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);
8710       PetscCall(MatDestroy(y));
8711     }
8712   }
8713 
8714   if (w && *y == w) { /* this is to minimize changes in PCMG */
8715     PetscBool flg;
8716 
8717     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8718     if (w) {
8719       PetscInt My, Ny, Mw, Nw;
8720 
8721       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8722       PetscCall(MatGetSize(*y, &My, &Ny));
8723       PetscCall(MatGetSize(w, &Mw, &Nw));
8724       if (!flg || My != Mw || Ny != Nw) w = NULL;
8725     }
8726     if (!w) {
8727       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8728       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8729       PetscCall(PetscObjectDereference((PetscObject)w));
8730     } else {
8731       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8732     }
8733   }
8734   if (!trans) {
8735     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8736   } else {
8737     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8738   }
8739   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8740   PetscFunctionReturn(PETSC_SUCCESS);
8741 }
8742 
8743 /*@
8744   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8745 
8746   Neighbor-wise Collective
8747 
8748   Input Parameters:
8749 + A - the matrix
8750 - x - the input dense matrix
8751 
8752   Output Parameter:
8753 . y - the output dense matrix
8754 
8755   Level: intermediate
8756 
8757   Note:
8758   This allows one to use either the restriction or interpolation (its transpose)
8759   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8760   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8761 
8762 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8763 @*/
8764 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8765 {
8766   PetscFunctionBegin;
8767   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8768   PetscFunctionReturn(PETSC_SUCCESS);
8769 }
8770 
8771 /*@
8772   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8773 
8774   Neighbor-wise Collective
8775 
8776   Input Parameters:
8777 + A - the matrix
8778 - x - the input dense matrix
8779 
8780   Output Parameter:
8781 . y - the output dense matrix
8782 
8783   Level: intermediate
8784 
8785   Note:
8786   This allows one to use either the restriction or interpolation (its transpose)
8787   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8788   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8789 
8790 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8791 @*/
8792 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8793 {
8794   PetscFunctionBegin;
8795   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8796   PetscFunctionReturn(PETSC_SUCCESS);
8797 }
8798 
8799 /*@
8800   MatGetNullSpace - retrieves the null space of a matrix.
8801 
8802   Logically Collective
8803 
8804   Input Parameters:
8805 + mat    - the matrix
8806 - nullsp - the null space object
8807 
8808   Level: developer
8809 
8810 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8811 @*/
8812 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8813 {
8814   PetscFunctionBegin;
8815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8816   PetscAssertPointer(nullsp, 2);
8817   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8818   PetscFunctionReturn(PETSC_SUCCESS);
8819 }
8820 
8821 /*@
8822   MatSetNullSpace - attaches a null space to a matrix.
8823 
8824   Logically Collective
8825 
8826   Input Parameters:
8827 + mat    - the matrix
8828 - nullsp - the null space object
8829 
8830   Level: advanced
8831 
8832   Notes:
8833   This null space is used by the `KSP` linear solvers to solve singular systems.
8834 
8835   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`
8836 
8837   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
8838   to zero but the linear system will still be solved in a least squares sense.
8839 
8840   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8841   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)$.
8842   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
8843   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
8844   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$).
8845   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8846 
8847   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8848   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8849   routine also automatically calls `MatSetTransposeNullSpace()`.
8850 
8851   The user should call `MatNullSpaceDestroy()`.
8852 
8853 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8854           `KSPSetPCSide()`
8855 @*/
8856 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8857 {
8858   PetscFunctionBegin;
8859   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8860   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8861   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8862   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8863   mat->nullsp = nullsp;
8864   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8865   PetscFunctionReturn(PETSC_SUCCESS);
8866 }
8867 
8868 /*@
8869   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8870 
8871   Logically Collective
8872 
8873   Input Parameters:
8874 + mat    - the matrix
8875 - nullsp - the null space object
8876 
8877   Level: developer
8878 
8879 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8880 @*/
8881 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8882 {
8883   PetscFunctionBegin;
8884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8885   PetscValidType(mat, 1);
8886   PetscAssertPointer(nullsp, 2);
8887   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8888   PetscFunctionReturn(PETSC_SUCCESS);
8889 }
8890 
8891 /*@
8892   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8893 
8894   Logically Collective
8895 
8896   Input Parameters:
8897 + mat    - the matrix
8898 - nullsp - the null space object
8899 
8900   Level: advanced
8901 
8902   Notes:
8903   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8904 
8905   See `MatSetNullSpace()`
8906 
8907 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8908 @*/
8909 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8910 {
8911   PetscFunctionBegin;
8912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8913   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8914   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8915   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8916   mat->transnullsp = nullsp;
8917   PetscFunctionReturn(PETSC_SUCCESS);
8918 }
8919 
8920 /*@
8921   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8922   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8923 
8924   Logically Collective
8925 
8926   Input Parameters:
8927 + mat    - the matrix
8928 - nullsp - the null space object
8929 
8930   Level: advanced
8931 
8932   Notes:
8933   Overwrites any previous near null space that may have been attached
8934 
8935   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8936 
8937 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8938 @*/
8939 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8940 {
8941   PetscFunctionBegin;
8942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8943   PetscValidType(mat, 1);
8944   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8945   MatCheckPreallocated(mat, 1);
8946   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8947   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8948   mat->nearnullsp = nullsp;
8949   PetscFunctionReturn(PETSC_SUCCESS);
8950 }
8951 
8952 /*@
8953   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8954 
8955   Not Collective
8956 
8957   Input Parameter:
8958 . mat - the matrix
8959 
8960   Output Parameter:
8961 . nullsp - the null space object, `NULL` if not set
8962 
8963   Level: advanced
8964 
8965 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8966 @*/
8967 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8968 {
8969   PetscFunctionBegin;
8970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8971   PetscValidType(mat, 1);
8972   PetscAssertPointer(nullsp, 2);
8973   MatCheckPreallocated(mat, 1);
8974   *nullsp = mat->nearnullsp;
8975   PetscFunctionReturn(PETSC_SUCCESS);
8976 }
8977 
8978 /*@C
8979   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8980 
8981   Collective
8982 
8983   Input Parameters:
8984 + mat  - the matrix
8985 . row  - row/column permutation
8986 - info - information on desired factorization process
8987 
8988   Level: developer
8989 
8990   Notes:
8991   Probably really in-place only when level of fill is zero, otherwise allocates
8992   new space to store factored matrix and deletes previous memory.
8993 
8994   Most users should employ the `KSP` interface for linear solvers
8995   instead of working directly with matrix algebra routines such as this.
8996   See, e.g., `KSPCreate()`.
8997 
8998   Developer Note:
8999   The Fortran interface is not autogenerated as the
9000   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9001 
9002 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9003 @*/
9004 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9005 {
9006   PetscFunctionBegin;
9007   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9008   PetscValidType(mat, 1);
9009   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9010   PetscAssertPointer(info, 3);
9011   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9012   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9013   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9014   MatCheckPreallocated(mat, 1);
9015   PetscUseTypeMethod(mat, iccfactor, row, info);
9016   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9017   PetscFunctionReturn(PETSC_SUCCESS);
9018 }
9019 
9020 /*@
9021   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9022   ghosted ones.
9023 
9024   Not Collective
9025 
9026   Input Parameters:
9027 + mat  - the matrix
9028 - diag - the diagonal values, including ghost ones
9029 
9030   Level: developer
9031 
9032   Notes:
9033   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9034 
9035   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9036 
9037 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9038 @*/
9039 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9040 {
9041   PetscMPIInt size;
9042 
9043   PetscFunctionBegin;
9044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9045   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9046   PetscValidType(mat, 1);
9047 
9048   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9049   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9050   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9051   if (size == 1) {
9052     PetscInt n, m;
9053     PetscCall(VecGetSize(diag, &n));
9054     PetscCall(MatGetSize(mat, NULL, &m));
9055     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9056     PetscCall(MatDiagonalScale(mat, NULL, diag));
9057   } else {
9058     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9059   }
9060   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9061   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9062   PetscFunctionReturn(PETSC_SUCCESS);
9063 }
9064 
9065 /*@
9066   MatGetInertia - Gets the inertia from a factored matrix
9067 
9068   Collective
9069 
9070   Input Parameter:
9071 . mat - the matrix
9072 
9073   Output Parameters:
9074 + nneg  - number of negative eigenvalues
9075 . nzero - number of zero eigenvalues
9076 - npos  - number of positive eigenvalues
9077 
9078   Level: advanced
9079 
9080   Note:
9081   Matrix must have been factored by `MatCholeskyFactor()`
9082 
9083 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9084 @*/
9085 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9086 {
9087   PetscFunctionBegin;
9088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9089   PetscValidType(mat, 1);
9090   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9091   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9092   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9093   PetscFunctionReturn(PETSC_SUCCESS);
9094 }
9095 
9096 /*@C
9097   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9098 
9099   Neighbor-wise Collective
9100 
9101   Input Parameters:
9102 + mat - the factored matrix obtained with `MatGetFactor()`
9103 - b   - the right-hand-side vectors
9104 
9105   Output Parameter:
9106 . x - the result vectors
9107 
9108   Level: developer
9109 
9110   Note:
9111   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9112   call `MatSolves`(A,x,x).
9113 
9114 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9115 @*/
9116 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9117 {
9118   PetscFunctionBegin;
9119   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9120   PetscValidType(mat, 1);
9121   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9122   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9123   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9124 
9125   MatCheckPreallocated(mat, 1);
9126   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9127   PetscUseTypeMethod(mat, solves, b, x);
9128   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9129   PetscFunctionReturn(PETSC_SUCCESS);
9130 }
9131 
9132 /*@
9133   MatIsSymmetric - Test whether a matrix is symmetric
9134 
9135   Collective
9136 
9137   Input Parameters:
9138 + A   - the matrix to test
9139 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9140 
9141   Output Parameter:
9142 . flg - the result
9143 
9144   Level: intermediate
9145 
9146   Notes:
9147   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9148 
9149   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9150 
9151   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9152   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9153 
9154 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9155           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9156 @*/
9157 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9158 {
9159   PetscFunctionBegin;
9160   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9161   PetscAssertPointer(flg, 3);
9162 
9163   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9164   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9165   else {
9166     PetscUseTypeMethod(A, issymmetric, tol, flg);
9167     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9168   }
9169   PetscFunctionReturn(PETSC_SUCCESS);
9170 }
9171 
9172 /*@
9173   MatIsHermitian - Test whether a matrix is Hermitian
9174 
9175   Collective
9176 
9177   Input Parameters:
9178 + A   - the matrix to test
9179 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9180 
9181   Output Parameter:
9182 . flg - the result
9183 
9184   Level: intermediate
9185 
9186   Notes:
9187   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9188 
9189   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9190 
9191   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9192   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9193 
9194 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9195           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9196 @*/
9197 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9198 {
9199   PetscFunctionBegin;
9200   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9201   PetscAssertPointer(flg, 3);
9202 
9203   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9204   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9205   else {
9206     PetscUseTypeMethod(A, ishermitian, tol, flg);
9207     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9208   }
9209   PetscFunctionReturn(PETSC_SUCCESS);
9210 }
9211 
9212 /*@
9213   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9214 
9215   Not Collective
9216 
9217   Input Parameter:
9218 . A - the matrix to check
9219 
9220   Output Parameters:
9221 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9222 - flg - the result (only valid if set is `PETSC_TRUE`)
9223 
9224   Level: advanced
9225 
9226   Notes:
9227   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9228   if you want it explicitly checked
9229 
9230   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9231   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9232 
9233 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9234 @*/
9235 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9236 {
9237   PetscFunctionBegin;
9238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9239   PetscAssertPointer(set, 2);
9240   PetscAssertPointer(flg, 3);
9241   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9242     *set = PETSC_TRUE;
9243     *flg = PetscBool3ToBool(A->symmetric);
9244   } else {
9245     *set = PETSC_FALSE;
9246   }
9247   PetscFunctionReturn(PETSC_SUCCESS);
9248 }
9249 
9250 /*@
9251   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9252 
9253   Not Collective
9254 
9255   Input Parameter:
9256 . A - the matrix to check
9257 
9258   Output Parameters:
9259 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9260 - flg - the result (only valid if set is `PETSC_TRUE`)
9261 
9262   Level: advanced
9263 
9264   Notes:
9265   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9266 
9267   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9268   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9269 
9270 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9271 @*/
9272 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9273 {
9274   PetscFunctionBegin;
9275   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9276   PetscAssertPointer(set, 2);
9277   PetscAssertPointer(flg, 3);
9278   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9279     *set = PETSC_TRUE;
9280     *flg = PetscBool3ToBool(A->spd);
9281   } else {
9282     *set = PETSC_FALSE;
9283   }
9284   PetscFunctionReturn(PETSC_SUCCESS);
9285 }
9286 
9287 /*@
9288   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9289 
9290   Not Collective
9291 
9292   Input Parameter:
9293 . A - the matrix to check
9294 
9295   Output Parameters:
9296 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9297 - flg - the result (only valid if set is `PETSC_TRUE`)
9298 
9299   Level: advanced
9300 
9301   Notes:
9302   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9303   if you want it explicitly checked
9304 
9305   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9306   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9307 
9308 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9309 @*/
9310 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9311 {
9312   PetscFunctionBegin;
9313   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9314   PetscAssertPointer(set, 2);
9315   PetscAssertPointer(flg, 3);
9316   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9317     *set = PETSC_TRUE;
9318     *flg = PetscBool3ToBool(A->hermitian);
9319   } else {
9320     *set = PETSC_FALSE;
9321   }
9322   PetscFunctionReturn(PETSC_SUCCESS);
9323 }
9324 
9325 /*@
9326   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9327 
9328   Collective
9329 
9330   Input Parameter:
9331 . A - the matrix to test
9332 
9333   Output Parameter:
9334 . flg - the result
9335 
9336   Level: intermediate
9337 
9338   Notes:
9339   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9340 
9341   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
9342   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9343 
9344 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9345 @*/
9346 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9347 {
9348   PetscFunctionBegin;
9349   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9350   PetscAssertPointer(flg, 2);
9351   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9352     *flg = PetscBool3ToBool(A->structurally_symmetric);
9353   } else {
9354     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9355     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9356   }
9357   PetscFunctionReturn(PETSC_SUCCESS);
9358 }
9359 
9360 /*@
9361   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9362 
9363   Not Collective
9364 
9365   Input Parameter:
9366 . A - the matrix to check
9367 
9368   Output Parameters:
9369 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9370 - flg - the result (only valid if set is PETSC_TRUE)
9371 
9372   Level: advanced
9373 
9374   Notes:
9375   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
9376   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9377 
9378   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9379 
9380 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9381 @*/
9382 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9383 {
9384   PetscFunctionBegin;
9385   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9386   PetscAssertPointer(set, 2);
9387   PetscAssertPointer(flg, 3);
9388   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9389     *set = PETSC_TRUE;
9390     *flg = PetscBool3ToBool(A->structurally_symmetric);
9391   } else {
9392     *set = PETSC_FALSE;
9393   }
9394   PetscFunctionReturn(PETSC_SUCCESS);
9395 }
9396 
9397 /*@
9398   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9399   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9400 
9401   Not Collective
9402 
9403   Input Parameter:
9404 . mat - the matrix
9405 
9406   Output Parameters:
9407 + nstash    - the size of the stash
9408 . reallocs  - the number of additional mallocs incurred.
9409 . bnstash   - the size of the block stash
9410 - breallocs - the number of additional mallocs incurred.in the block stash
9411 
9412   Level: advanced
9413 
9414 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9415 @*/
9416 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9417 {
9418   PetscFunctionBegin;
9419   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9420   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9421   PetscFunctionReturn(PETSC_SUCCESS);
9422 }
9423 
9424 /*@C
9425   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9426   parallel layout, `PetscLayout` for rows and columns
9427 
9428   Collective
9429 
9430   Input Parameter:
9431 . mat - the matrix
9432 
9433   Output Parameters:
9434 + right - (optional) vector that the matrix can be multiplied against
9435 - left  - (optional) vector that the matrix vector product can be stored in
9436 
9437   Level: advanced
9438 
9439   Notes:
9440   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()`.
9441 
9442   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9443 
9444 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9445 @*/
9446 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9447 {
9448   PetscFunctionBegin;
9449   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9450   PetscValidType(mat, 1);
9451   if (mat->ops->getvecs) {
9452     PetscUseTypeMethod(mat, getvecs, right, left);
9453   } else {
9454     if (right) {
9455       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9456       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9457       PetscCall(VecSetType(*right, mat->defaultvectype));
9458 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9459       if (mat->boundtocpu && mat->bindingpropagates) {
9460         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9461         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9462       }
9463 #endif
9464     }
9465     if (left) {
9466       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9467       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9468       PetscCall(VecSetType(*left, mat->defaultvectype));
9469 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9470       if (mat->boundtocpu && mat->bindingpropagates) {
9471         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9472         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9473       }
9474 #endif
9475     }
9476   }
9477   PetscFunctionReturn(PETSC_SUCCESS);
9478 }
9479 
9480 /*@C
9481   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9482   with default values.
9483 
9484   Not Collective
9485 
9486   Input Parameter:
9487 . info - the `MatFactorInfo` data structure
9488 
9489   Level: developer
9490 
9491   Notes:
9492   The solvers are generally used through the `KSP` and `PC` objects, for example
9493   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9494 
9495   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9496 
9497   Developer Note:
9498   The Fortran interface is not autogenerated as the
9499   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9500 
9501 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9502 @*/
9503 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9504 {
9505   PetscFunctionBegin;
9506   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9507   PetscFunctionReturn(PETSC_SUCCESS);
9508 }
9509 
9510 /*@
9511   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9512 
9513   Collective
9514 
9515   Input Parameters:
9516 + mat - the factored matrix
9517 - is  - the index set defining the Schur indices (0-based)
9518 
9519   Level: advanced
9520 
9521   Notes:
9522   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9523 
9524   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9525 
9526   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9527 
9528 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9529           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9530 @*/
9531 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9532 {
9533   PetscErrorCode (*f)(Mat, IS);
9534 
9535   PetscFunctionBegin;
9536   PetscValidType(mat, 1);
9537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9538   PetscValidType(is, 2);
9539   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9540   PetscCheckSameComm(mat, 1, is, 2);
9541   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9542   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9543   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9544   PetscCall(MatDestroy(&mat->schur));
9545   PetscCall((*f)(mat, is));
9546   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9547   PetscFunctionReturn(PETSC_SUCCESS);
9548 }
9549 
9550 /*@
9551   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9552 
9553   Logically Collective
9554 
9555   Input Parameters:
9556 + F      - the factored matrix obtained by calling `MatGetFactor()`
9557 . S      - location where to return the Schur complement, can be `NULL`
9558 - status - the status of the Schur complement matrix, can be `NULL`
9559 
9560   Level: advanced
9561 
9562   Notes:
9563   You must call `MatFactorSetSchurIS()` before calling this routine.
9564 
9565   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9566 
9567   The routine provides a copy of the Schur matrix stored within the solver data structures.
9568   The caller must destroy the object when it is no longer needed.
9569   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9570 
9571   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)
9572 
9573   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9574 
9575   Developer Note:
9576   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9577   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9578 
9579 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9580 @*/
9581 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9582 {
9583   PetscFunctionBegin;
9584   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9585   if (S) PetscAssertPointer(S, 2);
9586   if (status) PetscAssertPointer(status, 3);
9587   if (S) {
9588     PetscErrorCode (*f)(Mat, Mat *);
9589 
9590     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9591     if (f) {
9592       PetscCall((*f)(F, S));
9593     } else {
9594       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9595     }
9596   }
9597   if (status) *status = F->schur_status;
9598   PetscFunctionReturn(PETSC_SUCCESS);
9599 }
9600 
9601 /*@
9602   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9603 
9604   Logically Collective
9605 
9606   Input Parameters:
9607 + F      - the factored matrix obtained by calling `MatGetFactor()`
9608 . S      - location where to return the Schur complement, can be `NULL`
9609 - status - the status of the Schur complement matrix, can be `NULL`
9610 
9611   Level: advanced
9612 
9613   Notes:
9614   You must call `MatFactorSetSchurIS()` before calling this routine.
9615 
9616   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9617 
9618   The routine returns a the Schur Complement stored within the data structures of the solver.
9619 
9620   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9621 
9622   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9623 
9624   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9625 
9626   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9627 
9628 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9629 @*/
9630 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9631 {
9632   PetscFunctionBegin;
9633   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9634   if (S) {
9635     PetscAssertPointer(S, 2);
9636     *S = F->schur;
9637   }
9638   if (status) {
9639     PetscAssertPointer(status, 3);
9640     *status = F->schur_status;
9641   }
9642   PetscFunctionReturn(PETSC_SUCCESS);
9643 }
9644 
9645 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9646 {
9647   Mat S = F->schur;
9648 
9649   PetscFunctionBegin;
9650   switch (F->schur_status) {
9651   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9652   case MAT_FACTOR_SCHUR_INVERTED:
9653     if (S) {
9654       S->ops->solve             = NULL;
9655       S->ops->matsolve          = NULL;
9656       S->ops->solvetranspose    = NULL;
9657       S->ops->matsolvetranspose = NULL;
9658       S->ops->solveadd          = NULL;
9659       S->ops->solvetransposeadd = NULL;
9660       S->factortype             = MAT_FACTOR_NONE;
9661       PetscCall(PetscFree(S->solvertype));
9662     }
9663   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9664     break;
9665   default:
9666     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9667   }
9668   PetscFunctionReturn(PETSC_SUCCESS);
9669 }
9670 
9671 /*@
9672   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9673 
9674   Logically Collective
9675 
9676   Input Parameters:
9677 + F      - the factored matrix obtained by calling `MatGetFactor()`
9678 . S      - location where the Schur complement is stored
9679 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9680 
9681   Level: advanced
9682 
9683 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9684 @*/
9685 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9686 {
9687   PetscFunctionBegin;
9688   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9689   if (S) {
9690     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9691     *S = NULL;
9692   }
9693   F->schur_status = status;
9694   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9695   PetscFunctionReturn(PETSC_SUCCESS);
9696 }
9697 
9698 /*@
9699   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9700 
9701   Logically Collective
9702 
9703   Input Parameters:
9704 + F   - the factored matrix obtained by calling `MatGetFactor()`
9705 . rhs - location where the right hand side of the Schur complement system is stored
9706 - sol - location where the solution of the Schur complement system has to be returned
9707 
9708   Level: advanced
9709 
9710   Notes:
9711   The sizes of the vectors should match the size of the Schur complement
9712 
9713   Must be called after `MatFactorSetSchurIS()`
9714 
9715 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9716 @*/
9717 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9718 {
9719   PetscFunctionBegin;
9720   PetscValidType(F, 1);
9721   PetscValidType(rhs, 2);
9722   PetscValidType(sol, 3);
9723   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9724   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9725   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9726   PetscCheckSameComm(F, 1, rhs, 2);
9727   PetscCheckSameComm(F, 1, sol, 3);
9728   PetscCall(MatFactorFactorizeSchurComplement(F));
9729   switch (F->schur_status) {
9730   case MAT_FACTOR_SCHUR_FACTORED:
9731     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9732     break;
9733   case MAT_FACTOR_SCHUR_INVERTED:
9734     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9735     break;
9736   default:
9737     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9738   }
9739   PetscFunctionReturn(PETSC_SUCCESS);
9740 }
9741 
9742 /*@
9743   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9744 
9745   Logically Collective
9746 
9747   Input Parameters:
9748 + F   - the factored matrix obtained by calling `MatGetFactor()`
9749 . rhs - location where the right hand side of the Schur complement system is stored
9750 - sol - location where the solution of the Schur complement system has to be returned
9751 
9752   Level: advanced
9753 
9754   Notes:
9755   The sizes of the vectors should match the size of the Schur complement
9756 
9757   Must be called after `MatFactorSetSchurIS()`
9758 
9759 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9760 @*/
9761 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9762 {
9763   PetscFunctionBegin;
9764   PetscValidType(F, 1);
9765   PetscValidType(rhs, 2);
9766   PetscValidType(sol, 3);
9767   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9768   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9769   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9770   PetscCheckSameComm(F, 1, rhs, 2);
9771   PetscCheckSameComm(F, 1, sol, 3);
9772   PetscCall(MatFactorFactorizeSchurComplement(F));
9773   switch (F->schur_status) {
9774   case MAT_FACTOR_SCHUR_FACTORED:
9775     PetscCall(MatSolve(F->schur, rhs, sol));
9776     break;
9777   case MAT_FACTOR_SCHUR_INVERTED:
9778     PetscCall(MatMult(F->schur, rhs, sol));
9779     break;
9780   default:
9781     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9782   }
9783   PetscFunctionReturn(PETSC_SUCCESS);
9784 }
9785 
9786 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9787 #if PetscDefined(HAVE_CUDA)
9788 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9789 #endif
9790 
9791 /* Schur status updated in the interface */
9792 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9793 {
9794   Mat S = F->schur;
9795 
9796   PetscFunctionBegin;
9797   if (S) {
9798     PetscMPIInt size;
9799     PetscBool   isdense, isdensecuda;
9800 
9801     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9802     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9803     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9804     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9805     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9806     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9807     if (isdense) {
9808       PetscCall(MatSeqDenseInvertFactors_Private(S));
9809     } else if (isdensecuda) {
9810 #if defined(PETSC_HAVE_CUDA)
9811       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9812 #endif
9813     }
9814     // HIP??????????????
9815     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9816   }
9817   PetscFunctionReturn(PETSC_SUCCESS);
9818 }
9819 
9820 /*@
9821   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9822 
9823   Logically Collective
9824 
9825   Input Parameter:
9826 . F - the factored matrix obtained by calling `MatGetFactor()`
9827 
9828   Level: advanced
9829 
9830   Notes:
9831   Must be called after `MatFactorSetSchurIS()`.
9832 
9833   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9834 
9835 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9836 @*/
9837 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9838 {
9839   PetscFunctionBegin;
9840   PetscValidType(F, 1);
9841   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9842   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9843   PetscCall(MatFactorFactorizeSchurComplement(F));
9844   PetscCall(MatFactorInvertSchurComplement_Private(F));
9845   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9846   PetscFunctionReturn(PETSC_SUCCESS);
9847 }
9848 
9849 /*@
9850   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9851 
9852   Logically Collective
9853 
9854   Input Parameter:
9855 . F - the factored matrix obtained by calling `MatGetFactor()`
9856 
9857   Level: advanced
9858 
9859   Note:
9860   Must be called after `MatFactorSetSchurIS()`
9861 
9862 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9863 @*/
9864 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9865 {
9866   MatFactorInfo info;
9867 
9868   PetscFunctionBegin;
9869   PetscValidType(F, 1);
9870   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9871   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9872   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9873   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9874   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9875     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9876   } else {
9877     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9878   }
9879   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9880   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9881   PetscFunctionReturn(PETSC_SUCCESS);
9882 }
9883 
9884 /*@
9885   MatPtAP - Creates the matrix product $C = P^T * A * P$
9886 
9887   Neighbor-wise Collective
9888 
9889   Input Parameters:
9890 + A     - the matrix
9891 . P     - the projection matrix
9892 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9893 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9894           if the result is a dense matrix this is irrelevant
9895 
9896   Output Parameter:
9897 . C - the product matrix
9898 
9899   Level: intermediate
9900 
9901   Notes:
9902   C will be created and must be destroyed by the user with `MatDestroy()`.
9903 
9904   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9905 
9906   Developer Note:
9907   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9908 
9909 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9910 @*/
9911 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9912 {
9913   PetscFunctionBegin;
9914   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9915   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9916 
9917   if (scall == MAT_INITIAL_MATRIX) {
9918     PetscCall(MatProductCreate(A, P, NULL, C));
9919     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9920     PetscCall(MatProductSetAlgorithm(*C, "default"));
9921     PetscCall(MatProductSetFill(*C, fill));
9922 
9923     (*C)->product->api_user = PETSC_TRUE;
9924     PetscCall(MatProductSetFromOptions(*C));
9925     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);
9926     PetscCall(MatProductSymbolic(*C));
9927   } else { /* scall == MAT_REUSE_MATRIX */
9928     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9929   }
9930 
9931   PetscCall(MatProductNumeric(*C));
9932   (*C)->symmetric = A->symmetric;
9933   (*C)->spd       = A->spd;
9934   PetscFunctionReturn(PETSC_SUCCESS);
9935 }
9936 
9937 /*@
9938   MatRARt - Creates the matrix product $C = R * A * R^T$
9939 
9940   Neighbor-wise Collective
9941 
9942   Input Parameters:
9943 + A     - the matrix
9944 . R     - the projection matrix
9945 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9946 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9947           if the result is a dense matrix this is irrelevant
9948 
9949   Output Parameter:
9950 . C - the product matrix
9951 
9952   Level: intermediate
9953 
9954   Notes:
9955   C will be created and must be destroyed by the user with `MatDestroy()`.
9956 
9957   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9958 
9959   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9960   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9961   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9962   We recommend using MatPtAP().
9963 
9964 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9965 @*/
9966 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9967 {
9968   PetscFunctionBegin;
9969   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9970   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9971 
9972   if (scall == MAT_INITIAL_MATRIX) {
9973     PetscCall(MatProductCreate(A, R, NULL, C));
9974     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9975     PetscCall(MatProductSetAlgorithm(*C, "default"));
9976     PetscCall(MatProductSetFill(*C, fill));
9977 
9978     (*C)->product->api_user = PETSC_TRUE;
9979     PetscCall(MatProductSetFromOptions(*C));
9980     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);
9981     PetscCall(MatProductSymbolic(*C));
9982   } else { /* scall == MAT_REUSE_MATRIX */
9983     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9984   }
9985 
9986   PetscCall(MatProductNumeric(*C));
9987   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9988   PetscFunctionReturn(PETSC_SUCCESS);
9989 }
9990 
9991 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9992 {
9993   PetscFunctionBegin;
9994   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9995 
9996   if (scall == MAT_INITIAL_MATRIX) {
9997     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9998     PetscCall(MatProductCreate(A, B, NULL, C));
9999     PetscCall(MatProductSetType(*C, ptype));
10000     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10001     PetscCall(MatProductSetFill(*C, fill));
10002 
10003     (*C)->product->api_user = PETSC_TRUE;
10004     PetscCall(MatProductSetFromOptions(*C));
10005     PetscCall(MatProductSymbolic(*C));
10006   } else { /* scall == MAT_REUSE_MATRIX */
10007     Mat_Product *product = (*C)->product;
10008     PetscBool    isdense;
10009 
10010     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10011     if (isdense && product && product->type != ptype) {
10012       PetscCall(MatProductClear(*C));
10013       product = NULL;
10014     }
10015     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10016     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10017       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10018       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10019       product           = (*C)->product;
10020       product->fill     = fill;
10021       product->api_user = PETSC_TRUE;
10022       product->clear    = PETSC_TRUE;
10023 
10024       PetscCall(MatProductSetType(*C, ptype));
10025       PetscCall(MatProductSetFromOptions(*C));
10026       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);
10027       PetscCall(MatProductSymbolic(*C));
10028     } else { /* user may change input matrices A or B when REUSE */
10029       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10030     }
10031   }
10032   PetscCall(MatProductNumeric(*C));
10033   PetscFunctionReturn(PETSC_SUCCESS);
10034 }
10035 
10036 /*@
10037   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10038 
10039   Neighbor-wise Collective
10040 
10041   Input Parameters:
10042 + A     - the left matrix
10043 . B     - the right matrix
10044 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10045 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10046           if the result is a dense matrix this is irrelevant
10047 
10048   Output Parameter:
10049 . C - the product matrix
10050 
10051   Notes:
10052   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10053 
10054   `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
10055   call to this function with `MAT_INITIAL_MATRIX`.
10056 
10057   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10058 
10059   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`,
10060   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10061 
10062   Example of Usage:
10063 .vb
10064      MatProductCreate(A,B,NULL,&C);
10065      MatProductSetType(C,MATPRODUCT_AB);
10066      MatProductSymbolic(C);
10067      MatProductNumeric(C); // compute C=A * B
10068      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10069      MatProductNumeric(C);
10070      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10071      MatProductNumeric(C);
10072 .ve
10073 
10074   Level: intermediate
10075 
10076 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10077 @*/
10078 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10079 {
10080   PetscFunctionBegin;
10081   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10082   PetscFunctionReturn(PETSC_SUCCESS);
10083 }
10084 
10085 /*@
10086   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10087 
10088   Neighbor-wise Collective
10089 
10090   Input Parameters:
10091 + A     - the left matrix
10092 . B     - the right matrix
10093 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10094 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10095 
10096   Output Parameter:
10097 . C - the product matrix
10098 
10099   Options Database Key:
10100 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10101               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10102               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10103 
10104   Level: intermediate
10105 
10106   Notes:
10107   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10108 
10109   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10110 
10111   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10112   actually needed.
10113 
10114   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10115   and for pairs of `MATMPIDENSE` matrices.
10116 
10117   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10118 
10119 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10120 @*/
10121 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10122 {
10123   PetscFunctionBegin;
10124   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10125   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10126   PetscFunctionReturn(PETSC_SUCCESS);
10127 }
10128 
10129 /*@
10130   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10131 
10132   Neighbor-wise Collective
10133 
10134   Input Parameters:
10135 + A     - the left matrix
10136 . B     - the right matrix
10137 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10138 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10139 
10140   Output Parameter:
10141 . C - the product matrix
10142 
10143   Level: intermediate
10144 
10145   Notes:
10146   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10147 
10148   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10149 
10150   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10151 
10152   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10153   actually needed.
10154 
10155   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10156   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10157 
10158 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10159 @*/
10160 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10161 {
10162   PetscFunctionBegin;
10163   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10164   PetscFunctionReturn(PETSC_SUCCESS);
10165 }
10166 
10167 /*@
10168   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10169 
10170   Neighbor-wise Collective
10171 
10172   Input Parameters:
10173 + A     - the left matrix
10174 . B     - the middle matrix
10175 . C     - the right matrix
10176 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10177 - 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
10178           if the result is a dense matrix this is irrelevant
10179 
10180   Output Parameter:
10181 . D - the product matrix
10182 
10183   Level: intermediate
10184 
10185   Notes:
10186   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10187 
10188   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10189 
10190   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10191 
10192   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10193   actually needed.
10194 
10195   If you have many matrices with the same non-zero structure to multiply, you
10196   should use `MAT_REUSE_MATRIX` in all calls but the first
10197 
10198 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10199 @*/
10200 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10201 {
10202   PetscFunctionBegin;
10203   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10204   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10205 
10206   if (scall == MAT_INITIAL_MATRIX) {
10207     PetscCall(MatProductCreate(A, B, C, D));
10208     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10209     PetscCall(MatProductSetAlgorithm(*D, "default"));
10210     PetscCall(MatProductSetFill(*D, fill));
10211 
10212     (*D)->product->api_user = PETSC_TRUE;
10213     PetscCall(MatProductSetFromOptions(*D));
10214     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,
10215                ((PetscObject)C)->type_name);
10216     PetscCall(MatProductSymbolic(*D));
10217   } else { /* user may change input matrices when REUSE */
10218     PetscCall(MatProductReplaceMats(A, B, C, *D));
10219   }
10220   PetscCall(MatProductNumeric(*D));
10221   PetscFunctionReturn(PETSC_SUCCESS);
10222 }
10223 
10224 /*@
10225   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10226 
10227   Collective
10228 
10229   Input Parameters:
10230 + mat      - the matrix
10231 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10232 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10233 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10234 
10235   Output Parameter:
10236 . matredundant - redundant matrix
10237 
10238   Level: advanced
10239 
10240   Notes:
10241   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10242   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10243 
10244   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10245   calling it.
10246 
10247   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10248 
10249 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10250 @*/
10251 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10252 {
10253   MPI_Comm       comm;
10254   PetscMPIInt    size;
10255   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10256   Mat_Redundant *redund     = NULL;
10257   PetscSubcomm   psubcomm   = NULL;
10258   MPI_Comm       subcomm_in = subcomm;
10259   Mat           *matseq;
10260   IS             isrow, iscol;
10261   PetscBool      newsubcomm = PETSC_FALSE;
10262 
10263   PetscFunctionBegin;
10264   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10265   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10266     PetscAssertPointer(*matredundant, 5);
10267     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10268   }
10269 
10270   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10271   if (size == 1 || nsubcomm == 1) {
10272     if (reuse == MAT_INITIAL_MATRIX) {
10273       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10274     } else {
10275       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");
10276       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10277     }
10278     PetscFunctionReturn(PETSC_SUCCESS);
10279   }
10280 
10281   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10282   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10283   MatCheckPreallocated(mat, 1);
10284 
10285   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10286   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10287     /* create psubcomm, then get subcomm */
10288     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10289     PetscCallMPI(MPI_Comm_size(comm, &size));
10290     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10291 
10292     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10293     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10294     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10295     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10296     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10297     newsubcomm = PETSC_TRUE;
10298     PetscCall(PetscSubcommDestroy(&psubcomm));
10299   }
10300 
10301   /* get isrow, iscol and a local sequential matrix matseq[0] */
10302   if (reuse == MAT_INITIAL_MATRIX) {
10303     mloc_sub = PETSC_DECIDE;
10304     nloc_sub = PETSC_DECIDE;
10305     if (bs < 1) {
10306       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10307       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10308     } else {
10309       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10310       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10311     }
10312     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10313     rstart = rend - mloc_sub;
10314     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10315     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10316     PetscCall(ISSetIdentity(iscol));
10317   } else { /* reuse == MAT_REUSE_MATRIX */
10318     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");
10319     /* retrieve subcomm */
10320     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10321     redund = (*matredundant)->redundant;
10322     isrow  = redund->isrow;
10323     iscol  = redund->iscol;
10324     matseq = redund->matseq;
10325   }
10326   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10327 
10328   /* get matredundant over subcomm */
10329   if (reuse == MAT_INITIAL_MATRIX) {
10330     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10331 
10332     /* create a supporting struct and attach it to C for reuse */
10333     PetscCall(PetscNew(&redund));
10334     (*matredundant)->redundant = redund;
10335     redund->isrow              = isrow;
10336     redund->iscol              = iscol;
10337     redund->matseq             = matseq;
10338     if (newsubcomm) {
10339       redund->subcomm = subcomm;
10340     } else {
10341       redund->subcomm = MPI_COMM_NULL;
10342     }
10343   } else {
10344     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10345   }
10346 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10347   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10348     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10349     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10350   }
10351 #endif
10352   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10353   PetscFunctionReturn(PETSC_SUCCESS);
10354 }
10355 
10356 /*@C
10357   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10358   a given `Mat`. Each submatrix can span multiple procs.
10359 
10360   Collective
10361 
10362   Input Parameters:
10363 + mat     - the matrix
10364 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10365 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10366 
10367   Output Parameter:
10368 . subMat - parallel sub-matrices each spanning a given `subcomm`
10369 
10370   Level: advanced
10371 
10372   Notes:
10373   The submatrix partition across processors is dictated by `subComm` a
10374   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10375   is not restricted to be grouped with consecutive original MPI processes.
10376 
10377   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10378   map directly to the layout of the original matrix [wrt the local
10379   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10380   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10381   the `subMat`. However the offDiagMat looses some columns - and this is
10382   reconstructed with `MatSetValues()`
10383 
10384   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10385 
10386 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10387 @*/
10388 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10389 {
10390   PetscMPIInt commsize, subCommSize;
10391 
10392   PetscFunctionBegin;
10393   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10394   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10395   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10396 
10397   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");
10398   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10399   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10400   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10401   PetscFunctionReturn(PETSC_SUCCESS);
10402 }
10403 
10404 /*@
10405   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10406 
10407   Not Collective
10408 
10409   Input Parameters:
10410 + mat   - matrix to extract local submatrix from
10411 . isrow - local row indices for submatrix
10412 - iscol - local column indices for submatrix
10413 
10414   Output Parameter:
10415 . submat - the submatrix
10416 
10417   Level: intermediate
10418 
10419   Notes:
10420   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10421 
10422   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10423   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10424 
10425   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10426   `MatSetValuesBlockedLocal()` will also be implemented.
10427 
10428   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10429   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10430 
10431 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10432 @*/
10433 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10434 {
10435   PetscFunctionBegin;
10436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10437   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10438   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10439   PetscCheckSameComm(isrow, 2, iscol, 3);
10440   PetscAssertPointer(submat, 4);
10441   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10442 
10443   if (mat->ops->getlocalsubmatrix) {
10444     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10445   } else {
10446     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10447   }
10448   PetscFunctionReturn(PETSC_SUCCESS);
10449 }
10450 
10451 /*@
10452   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10453 
10454   Not Collective
10455 
10456   Input Parameters:
10457 + mat    - matrix to extract local submatrix from
10458 . isrow  - local row indices for submatrix
10459 . iscol  - local column indices for submatrix
10460 - submat - the submatrix
10461 
10462   Level: intermediate
10463 
10464 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10465 @*/
10466 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10467 {
10468   PetscFunctionBegin;
10469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10470   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10471   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10472   PetscCheckSameComm(isrow, 2, iscol, 3);
10473   PetscAssertPointer(submat, 4);
10474   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10475 
10476   if (mat->ops->restorelocalsubmatrix) {
10477     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10478   } else {
10479     PetscCall(MatDestroy(submat));
10480   }
10481   *submat = NULL;
10482   PetscFunctionReturn(PETSC_SUCCESS);
10483 }
10484 
10485 /*@
10486   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10487 
10488   Collective
10489 
10490   Input Parameter:
10491 . mat - the matrix
10492 
10493   Output Parameter:
10494 . is - if any rows have zero diagonals this contains the list of them
10495 
10496   Level: developer
10497 
10498 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10499 @*/
10500 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10501 {
10502   PetscFunctionBegin;
10503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10504   PetscValidType(mat, 1);
10505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10507 
10508   if (!mat->ops->findzerodiagonals) {
10509     Vec                diag;
10510     const PetscScalar *a;
10511     PetscInt          *rows;
10512     PetscInt           rStart, rEnd, r, nrow = 0;
10513 
10514     PetscCall(MatCreateVecs(mat, &diag, NULL));
10515     PetscCall(MatGetDiagonal(mat, diag));
10516     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10517     PetscCall(VecGetArrayRead(diag, &a));
10518     for (r = 0; r < rEnd - rStart; ++r)
10519       if (a[r] == 0.0) ++nrow;
10520     PetscCall(PetscMalloc1(nrow, &rows));
10521     nrow = 0;
10522     for (r = 0; r < rEnd - rStart; ++r)
10523       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10524     PetscCall(VecRestoreArrayRead(diag, &a));
10525     PetscCall(VecDestroy(&diag));
10526     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10527   } else {
10528     PetscUseTypeMethod(mat, findzerodiagonals, is);
10529   }
10530   PetscFunctionReturn(PETSC_SUCCESS);
10531 }
10532 
10533 /*@
10534   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10535 
10536   Collective
10537 
10538   Input Parameter:
10539 . mat - the matrix
10540 
10541   Output Parameter:
10542 . is - contains the list of rows with off block diagonal entries
10543 
10544   Level: developer
10545 
10546 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10547 @*/
10548 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10549 {
10550   PetscFunctionBegin;
10551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10552   PetscValidType(mat, 1);
10553   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10554   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10555 
10556   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10557   PetscFunctionReturn(PETSC_SUCCESS);
10558 }
10559 
10560 /*@C
10561   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10562 
10563   Collective; No Fortran Support
10564 
10565   Input Parameter:
10566 . mat - the matrix
10567 
10568   Output Parameter:
10569 . values - the block inverses in column major order (FORTRAN-like)
10570 
10571   Level: advanced
10572 
10573   Notes:
10574   The size of the blocks is determined by the block size of the matrix.
10575 
10576   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10577 
10578   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10579 
10580 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10581 @*/
10582 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10583 {
10584   PetscFunctionBegin;
10585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10586   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10587   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10588   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10589   PetscFunctionReturn(PETSC_SUCCESS);
10590 }
10591 
10592 /*@C
10593   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10594 
10595   Collective; No Fortran Support
10596 
10597   Input Parameters:
10598 + mat     - the matrix
10599 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10600 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10601 
10602   Output Parameter:
10603 . values - the block inverses in column major order (FORTRAN-like)
10604 
10605   Level: advanced
10606 
10607   Notes:
10608   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10609 
10610   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10611 
10612 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10613 @*/
10614 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10615 {
10616   PetscFunctionBegin;
10617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10618   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10619   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10620   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10621   PetscFunctionReturn(PETSC_SUCCESS);
10622 }
10623 
10624 /*@
10625   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10626 
10627   Collective
10628 
10629   Input Parameters:
10630 + A - the matrix
10631 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10632 
10633   Level: advanced
10634 
10635   Note:
10636   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10637 
10638 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10639 @*/
10640 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10641 {
10642   const PetscScalar *vals;
10643   PetscInt          *dnnz;
10644   PetscInt           m, rstart, rend, bs, i, j;
10645 
10646   PetscFunctionBegin;
10647   PetscCall(MatInvertBlockDiagonal(A, &vals));
10648   PetscCall(MatGetBlockSize(A, &bs));
10649   PetscCall(MatGetLocalSize(A, &m, NULL));
10650   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10651   PetscCall(PetscMalloc1(m / bs, &dnnz));
10652   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10653   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10654   PetscCall(PetscFree(dnnz));
10655   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10656   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10657   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10658   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10659   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10660   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10661   PetscFunctionReturn(PETSC_SUCCESS);
10662 }
10663 
10664 /*@C
10665   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10666   via `MatTransposeColoringCreate()`.
10667 
10668   Collective
10669 
10670   Input Parameter:
10671 . c - coloring context
10672 
10673   Level: intermediate
10674 
10675 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10676 @*/
10677 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10678 {
10679   MatTransposeColoring matcolor = *c;
10680 
10681   PetscFunctionBegin;
10682   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10683   if (--((PetscObject)matcolor)->refct > 0) {
10684     matcolor = NULL;
10685     PetscFunctionReturn(PETSC_SUCCESS);
10686   }
10687 
10688   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10689   PetscCall(PetscFree(matcolor->rows));
10690   PetscCall(PetscFree(matcolor->den2sp));
10691   PetscCall(PetscFree(matcolor->colorforcol));
10692   PetscCall(PetscFree(matcolor->columns));
10693   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10694   PetscCall(PetscHeaderDestroy(c));
10695   PetscFunctionReturn(PETSC_SUCCESS);
10696 }
10697 
10698 /*@C
10699   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10700   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10701   `MatTransposeColoring` to sparse `B`.
10702 
10703   Collective
10704 
10705   Input Parameters:
10706 + coloring - coloring context created with `MatTransposeColoringCreate()`
10707 - B        - sparse matrix
10708 
10709   Output Parameter:
10710 . Btdense - dense matrix $B^T$
10711 
10712   Level: developer
10713 
10714   Note:
10715   These are used internally for some implementations of `MatRARt()`
10716 
10717 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10718 @*/
10719 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10720 {
10721   PetscFunctionBegin;
10722   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10723   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10724   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10725 
10726   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10727   PetscFunctionReturn(PETSC_SUCCESS);
10728 }
10729 
10730 /*@C
10731   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10732   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10733   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10734   $C_{sp}$ from $C_{den}$.
10735 
10736   Collective
10737 
10738   Input Parameters:
10739 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10740 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10741 
10742   Output Parameter:
10743 . Csp - sparse matrix
10744 
10745   Level: developer
10746 
10747   Note:
10748   These are used internally for some implementations of `MatRARt()`
10749 
10750 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10751 @*/
10752 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10753 {
10754   PetscFunctionBegin;
10755   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10756   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10757   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10758 
10759   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10760   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10761   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10762   PetscFunctionReturn(PETSC_SUCCESS);
10763 }
10764 
10765 /*@C
10766   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10767 
10768   Collective
10769 
10770   Input Parameters:
10771 + mat        - the matrix product C
10772 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10773 
10774   Output Parameter:
10775 . color - the new coloring context
10776 
10777   Level: intermediate
10778 
10779 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10780           `MatTransColoringApplyDenToSp()`
10781 @*/
10782 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10783 {
10784   MatTransposeColoring c;
10785   MPI_Comm             comm;
10786 
10787   PetscFunctionBegin;
10788   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10789   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10790   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10791 
10792   c->ctype = iscoloring->ctype;
10793   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10794 
10795   *color = c;
10796   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10797   PetscFunctionReturn(PETSC_SUCCESS);
10798 }
10799 
10800 /*@
10801   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10802   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10803   same, otherwise it will be larger
10804 
10805   Not Collective
10806 
10807   Input Parameter:
10808 . mat - the matrix
10809 
10810   Output Parameter:
10811 . state - the current state
10812 
10813   Level: intermediate
10814 
10815   Notes:
10816   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10817   different matrices
10818 
10819   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10820 
10821   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10822 
10823 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10824 @*/
10825 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10826 {
10827   PetscFunctionBegin;
10828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10829   *state = mat->nonzerostate;
10830   PetscFunctionReturn(PETSC_SUCCESS);
10831 }
10832 
10833 /*@
10834   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10835   matrices from each processor
10836 
10837   Collective
10838 
10839   Input Parameters:
10840 + comm   - the communicators the parallel matrix will live on
10841 . seqmat - the input sequential matrices
10842 . n      - number of local columns (or `PETSC_DECIDE`)
10843 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10844 
10845   Output Parameter:
10846 . mpimat - the parallel matrix generated
10847 
10848   Level: developer
10849 
10850   Note:
10851   The number of columns of the matrix in EACH processor MUST be the same.
10852 
10853 .seealso: [](ch_matrices), `Mat`
10854 @*/
10855 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10856 {
10857   PetscMPIInt size;
10858 
10859   PetscFunctionBegin;
10860   PetscCallMPI(MPI_Comm_size(comm, &size));
10861   if (size == 1) {
10862     if (reuse == MAT_INITIAL_MATRIX) {
10863       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10864     } else {
10865       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10866     }
10867     PetscFunctionReturn(PETSC_SUCCESS);
10868   }
10869 
10870   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");
10871 
10872   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10873   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10874   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10875   PetscFunctionReturn(PETSC_SUCCESS);
10876 }
10877 
10878 /*@
10879   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10880 
10881   Collective
10882 
10883   Input Parameters:
10884 + A - the matrix to create subdomains from
10885 - N - requested number of subdomains
10886 
10887   Output Parameters:
10888 + n   - number of subdomains resulting on this MPI process
10889 - iss - `IS` list with indices of subdomains on this MPI process
10890 
10891   Level: advanced
10892 
10893   Note:
10894   The number of subdomains must be smaller than the communicator size
10895 
10896 .seealso: [](ch_matrices), `Mat`, `IS`
10897 @*/
10898 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10899 {
10900   MPI_Comm    comm, subcomm;
10901   PetscMPIInt size, rank, color;
10902   PetscInt    rstart, rend, k;
10903 
10904   PetscFunctionBegin;
10905   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10906   PetscCallMPI(MPI_Comm_size(comm, &size));
10907   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10908   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);
10909   *n    = 1;
10910   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10911   color = rank / k;
10912   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10913   PetscCall(PetscMalloc1(1, iss));
10914   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10915   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10916   PetscCallMPI(MPI_Comm_free(&subcomm));
10917   PetscFunctionReturn(PETSC_SUCCESS);
10918 }
10919 
10920 /*@
10921   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10922 
10923   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10924   If they are not the same, uses `MatMatMatMult()`.
10925 
10926   Once the coarse grid problem is constructed, correct for interpolation operators
10927   that are not of full rank, which can legitimately happen in the case of non-nested
10928   geometric multigrid.
10929 
10930   Input Parameters:
10931 + restrct     - restriction operator
10932 . dA          - fine grid matrix
10933 . interpolate - interpolation operator
10934 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10935 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10936 
10937   Output Parameter:
10938 . A - the Galerkin coarse matrix
10939 
10940   Options Database Key:
10941 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10942 
10943   Level: developer
10944 
10945 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10946 @*/
10947 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10948 {
10949   IS  zerorows;
10950   Vec diag;
10951 
10952   PetscFunctionBegin;
10953   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10954   /* Construct the coarse grid matrix */
10955   if (interpolate == restrct) {
10956     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10957   } else {
10958     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10959   }
10960 
10961   /* If the interpolation matrix is not of full rank, A will have zero rows.
10962      This can legitimately happen in the case of non-nested geometric multigrid.
10963      In that event, we set the rows of the matrix to the rows of the identity,
10964      ignoring the equations (as the RHS will also be zero). */
10965 
10966   PetscCall(MatFindZeroRows(*A, &zerorows));
10967 
10968   if (zerorows != NULL) { /* if there are any zero rows */
10969     PetscCall(MatCreateVecs(*A, &diag, NULL));
10970     PetscCall(MatGetDiagonal(*A, diag));
10971     PetscCall(VecISSet(diag, zerorows, 1.0));
10972     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10973     PetscCall(VecDestroy(&diag));
10974     PetscCall(ISDestroy(&zerorows));
10975   }
10976   PetscFunctionReturn(PETSC_SUCCESS);
10977 }
10978 
10979 /*@C
10980   MatSetOperation - Allows user to set a matrix operation for any matrix type
10981 
10982   Logically Collective
10983 
10984   Input Parameters:
10985 + mat - the matrix
10986 . op  - the name of the operation
10987 - f   - the function that provides the operation
10988 
10989   Level: developer
10990 
10991   Example Usage:
10992 .vb
10993   extern PetscErrorCode usermult(Mat, Vec, Vec);
10994 
10995   PetscCall(MatCreateXXX(comm, ..., &A));
10996   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10997 .ve
10998 
10999   Notes:
11000   See the file `include/petscmat.h` for a complete list of matrix
11001   operations, which all have the form MATOP_<OPERATION>, where
11002   <OPERATION> is the name (in all capital letters) of the
11003   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11004 
11005   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11006   sequence as the usual matrix interface routines, since they
11007   are intended to be accessed via the usual matrix interface
11008   routines, e.g.,
11009 .vb
11010   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11011 .ve
11012 
11013   In particular each function MUST return `PETSC_SUCCESS` on success and
11014   nonzero on failure.
11015 
11016   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11017 
11018 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11019 @*/
11020 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11021 {
11022   PetscFunctionBegin;
11023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11024   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11025   (((void (**)(void))mat->ops)[op]) = f;
11026   PetscFunctionReturn(PETSC_SUCCESS);
11027 }
11028 
11029 /*@C
11030   MatGetOperation - Gets a matrix operation for any matrix type.
11031 
11032   Not Collective
11033 
11034   Input Parameters:
11035 + mat - the matrix
11036 - op  - the name of the operation
11037 
11038   Output Parameter:
11039 . f - the function that provides the operation
11040 
11041   Level: developer
11042 
11043   Example Usage:
11044 .vb
11045   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11046 
11047   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11048 .ve
11049 
11050   Notes:
11051   See the file include/petscmat.h for a complete list of matrix
11052   operations, which all have the form MATOP_<OPERATION>, where
11053   <OPERATION> is the name (in all capital letters) of the
11054   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11055 
11056   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11057 
11058 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11059 @*/
11060 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11061 {
11062   PetscFunctionBegin;
11063   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11064   *f = (((void (**)(void))mat->ops)[op]);
11065   PetscFunctionReturn(PETSC_SUCCESS);
11066 }
11067 
11068 /*@
11069   MatHasOperation - Determines whether the given matrix supports the particular operation.
11070 
11071   Not Collective
11072 
11073   Input Parameters:
11074 + mat - the matrix
11075 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11076 
11077   Output Parameter:
11078 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11079 
11080   Level: advanced
11081 
11082   Note:
11083   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11084 
11085 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11086 @*/
11087 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11088 {
11089   PetscFunctionBegin;
11090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11091   PetscAssertPointer(has, 3);
11092   if (mat->ops->hasoperation) {
11093     PetscUseTypeMethod(mat, hasoperation, op, has);
11094   } else {
11095     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11096     else {
11097       *has = PETSC_FALSE;
11098       if (op == MATOP_CREATE_SUBMATRIX) {
11099         PetscMPIInt size;
11100 
11101         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11102         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11103       }
11104     }
11105   }
11106   PetscFunctionReturn(PETSC_SUCCESS);
11107 }
11108 
11109 /*@
11110   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11111 
11112   Collective
11113 
11114   Input Parameter:
11115 . mat - the matrix
11116 
11117   Output Parameter:
11118 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11119 
11120   Level: beginner
11121 
11122 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11123 @*/
11124 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11125 {
11126   PetscFunctionBegin;
11127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11128   PetscValidType(mat, 1);
11129   PetscAssertPointer(cong, 2);
11130   if (!mat->rmap || !mat->cmap) {
11131     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11132     PetscFunctionReturn(PETSC_SUCCESS);
11133   }
11134   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11135     PetscCall(PetscLayoutSetUp(mat->rmap));
11136     PetscCall(PetscLayoutSetUp(mat->cmap));
11137     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11138     if (*cong) mat->congruentlayouts = 1;
11139     else mat->congruentlayouts = 0;
11140   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11141   PetscFunctionReturn(PETSC_SUCCESS);
11142 }
11143 
11144 PetscErrorCode MatSetInf(Mat A)
11145 {
11146   PetscFunctionBegin;
11147   PetscUseTypeMethod(A, setinf);
11148   PetscFunctionReturn(PETSC_SUCCESS);
11149 }
11150 
11151 /*@C
11152   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
11153   and possibly removes small values from the graph structure.
11154 
11155   Collective
11156 
11157   Input Parameters:
11158 + A      - the matrix
11159 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11160 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11161 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11162 
11163   Output Parameter:
11164 . graph - the resulting graph
11165 
11166   Level: advanced
11167 
11168 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11169 @*/
11170 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11171 {
11172   PetscFunctionBegin;
11173   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11174   PetscValidType(A, 1);
11175   PetscValidLogicalCollectiveBool(A, scale, 3);
11176   PetscAssertPointer(graph, 5);
11177   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11178   PetscFunctionReturn(PETSC_SUCCESS);
11179 }
11180 
11181 /*@
11182   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11183   meaning the same memory is used for the matrix, and no new memory is allocated.
11184 
11185   Collective
11186 
11187   Input Parameters:
11188 + A    - the matrix
11189 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well
11190 
11191   Level: intermediate
11192 
11193   Developer Note:
11194   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11195   of the arrays in the data structure are unneeded.
11196 
11197 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11198 @*/
11199 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11200 {
11201   PetscFunctionBegin;
11202   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11203   PetscUseTypeMethod(A, eliminatezeros, keep);
11204   PetscFunctionReturn(PETSC_SUCCESS);
11205 }
11206