xref: /petsc/src/mat/interface/matrix.c (revision 6bd3a4fd3ada34738ab3c62a7d3b0fa06ce8b47c)
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 locations it fills the locations with random numbers.
73 
74   It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](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()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143   MatFactorGetError - gets the error code from a factorization
144 
145   Logically Collective
146 
147   Input Parameter:
148 . mat - the factored matrix
149 
150   Output Parameter:
151 . err - the error code
152 
153   Level: advanced
154 
155   Note:
156   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171   MatFactorClearError - clears the error code in a factorization
172 
173   Logically Collective
174 
175   Input Parameter:
176 . mat - the factored matrix
177 
178   Level: developer
179 
180   Note:
181   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 . mat - the matrix
256 
257   Output Parameter:
258 . keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263   `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281   MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 . mat - the matrix
285 
286   Output Parameter:
287 . zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292   `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322   Not Collective
323 
324   Input Parameter:
325 . A - the matrix
326 
327   Output Parameter:
328 . a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330   Level: advanced
331 
332   Notes:
333   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360   Collective
361 
362   Input Parameter:
363 . mat - the matrix
364 
365   Output Parameter:
366 . trace - the sum of the diagonal entries
367 
368   Level: advanced
369 
370 .seealso: [](ch_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387   MatRealPart - Zeros out the imaginary part of the matrix
388 
389   Logically Collective
390 
391   Input Parameter:
392 . mat - the matrix
393 
394   Level: advanced
395 
396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413   Collective
414 
415   Input Parameter:
416 . mat - the matrix
417 
418   Output Parameters:
419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 - ghosts  - the global indices of the ghost points
421 
422   Level: advanced
423 
424   Note:
425   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447   Logically Collective
448 
449   Input Parameter:
450 . mat - the matrix
451 
452   Level: advanced
453 
454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471   Not Collective
472 
473   Input Parameter:
474 . mat - the matrix
475 
476   Output Parameters:
477 + missing - is any diagonal missing
478 - dd      - first diagonal entry that is missing (optional) on this process
479 
480   Level: advanced
481 
482 .seealso: [](ch_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
497 /*@C
498   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499   for each row that you get to ensure that your application does
500   not bleed memory.
501 
502   Not Collective
503 
504   Input Parameters:
505 + mat - the matrix
506 - row - the row to get
507 
508   Output Parameters:
509 + ncols - if not `NULL`, the number of nonzeros in the row
510 . cols  - if not `NULL`, the column numbers
511 - vals  - if not `NULL`, the values
512 
513   Level: advanced
514 
515   Notes:
516   This routine is provided for people who need to have direct access
517   to the structure of a matrix.  We hope that we provide enough
518   high-level matrix routines that few users will need it.
519 
520   `MatGetRow()` always returns 0-based column indices, regardless of
521   whether the internal representation is 0-based (default) or 1-based.
522 
523   For better efficiency, set cols and/or vals to `NULL` if you do
524   not wish to extract these quantities.
525 
526   The user can only examine the values extracted with `MatGetRow()`;
527   the values cannot be altered.  To change the matrix entries, one
528   must use `MatSetValues()`.
529 
530   You can only have one call to `MatGetRow()` outstanding for a particular
531   matrix at a time, per processor. `MatGetRow()` can only obtain rows
532   associated with the given processor, it cannot get rows from the
533   other processors; for that we suggest using `MatCreateSubMatrices()`, then
534   MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535   is in the global number of rows.
536 
537   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541   Fortran Notes:
542   The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551   where maxcols >= maximum nonzeros in any row of the matrix.
552 
553   Caution:
554   Do not try to change the contents of the output arrays (`cols` and `vals`).
555   In some cases, this may corrupt the matrix.
556 
557 .seealso: [](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) PetscValidIntPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657   Not Collective
658 
659   Input Parameter:
660 . mat - the matrix
661 
662   Level: advanced
663 
664   Note:
665   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
666 
667 .seealso: [](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     PetscValidCharPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778   for matrices created with `MatGetFactor()`
779 
780   Logically Collective
781 
782   Input Parameters:
783 + A      - the matrix
784 - prefix - the prefix to prepend to all option names for the factored matrix
785 
786   Level: developer
787 
788   Notes:
789   A hyphen (-) must NOT be given at the beginning of the prefix name.
790   The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](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 Notes:
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   PetscValidPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
877 
878   Collective
879 
880   Input Parameter:
881 . A - the matrix
882 
883   Level: beginner
884 
885   Notes:
886   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888   Users can reset the preallocation to access the original memory.
889 
890   Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](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   If a suitable preallocation routine is used, this function does not need to be called.
920 
921   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*
947    If threadsafety is on extraneous matrices may be printed
948 
949    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
950 */
951 #if !defined(PETSC_HAVE_THREADSAFETY)
952 static PetscInt insidematview = 0;
953 #endif
954 
955 /*@C
956   MatViewFromOptions - View properties of the matrix based on options set in the options database
957 
958   Collective
959 
960   Input Parameters:
961 + A    - the matrix
962 . obj  - optional additional object that provides the options prefix to use
963 - name - command line option
964 
965   Options Database Key:
966 . -mat_view [viewertype]:... - the viewer and its options
967 
968   Level: intermediate
969 
970   Notes:
971 .vb
972     If no value is provided ascii:stdout is used
973        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
974                                                   for example ascii::ascii_info prints just the information about the object not all details
975                                                   unless :append is given filename opens in write mode, overwriting what was already there
976        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
977        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
978        socket[:port]                             defaults to the standard output port
979        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
980 .ve
981 
982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
983 @*/
984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
985 {
986   PetscFunctionBegin;
987   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
988 #if !defined(PETSC_HAVE_THREADSAFETY)
989   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
990 #endif
991   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
992   PetscFunctionReturn(PETSC_SUCCESS);
993 }
994 
995 /*@C
996   MatView - display information about a matrix in a variety ways
997 
998   Collective
999 
1000   Input Parameters:
1001 + mat    - the matrix
1002 - viewer - visualization context
1003 
1004   Options Database Keys:
1005 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1006 . -mat_view ::ascii_info_detail    - Prints more detailed info
1007 . -mat_view                        - Prints matrix in ASCII format
1008 . -mat_view ::ascii_matlab         - Prints matrix in Matlab format
1009 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1010 . -display <name>                  - Sets display name (default is host)
1011 . -draw_pause <sec>                - Sets number of seconds to pause after display
1012 . -mat_view socket                 - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1013 . -viewer_socket_machine <machine> - -
1014 . -viewer_socket_port <port>       - -
1015 . -mat_view binary                 - save matrix to file in binary format
1016 - -viewer_binary_filename <name>   - -
1017 
1018   Level: beginner
1019 
1020   Notes:
1021   The available visualization contexts include
1022 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1023 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1024 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1025 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1026 
1027   The user can open alternative visualization contexts with
1028 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1029 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1030   specified file; corresponding input uses `MatLoad()`
1031 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1032   an X window display
1033 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1034   Currently only the `MATSEQDENSE` and `MATAIJ`
1035   matrix types support the Socket viewer.
1036 
1037   The user can call `PetscViewerPushFormat()` to specify the output
1038   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1039   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1040 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1041 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1042 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1043 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1044   format common among all matrix types
1045 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1046   format (which is in many cases the same as the default)
1047 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1048   size and structure (not the matrix entries)
1049 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1050   the matrix structure
1051 
1052   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1053   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1054 
1055   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1056 
1057   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1058   viewer is used.
1059 
1060   See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1061   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1062 
1063   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1064   and then use the following mouse functions.
1065 .vb
1066   left mouse: zoom in
1067   middle mouse: zoom out
1068   right mouse: continue with the simulation
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1072           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1073 @*/
1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1075 {
1076   PetscInt          rows, cols, rbs, cbs;
1077   PetscBool         isascii, isstring, issaws;
1078   PetscViewerFormat format;
1079   PetscMPIInt       size;
1080 
1081   PetscFunctionBegin;
1082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1083   PetscValidType(mat, 1);
1084   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1085   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1086   PetscCheckSameComm(mat, 1, viewer, 2);
1087 
1088   PetscCall(PetscViewerGetFormat(viewer, &format));
1089   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1090   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1091 
1092 #if !defined(PETSC_HAVE_THREADSAFETY)
1093   insidematview++;
1094 #endif
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1098   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");
1099 
1100   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1101   if (isascii) {
1102     if (!mat->preallocated) {
1103       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1104 #if !defined(PETSC_HAVE_THREADSAFETY)
1105       insidematview--;
1106 #endif
1107       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1108       PetscFunctionReturn(PETSC_SUCCESS);
1109     }
1110     if (!mat->assembled) {
1111       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1112 #if !defined(PETSC_HAVE_THREADSAFETY)
1113       insidematview--;
1114 #endif
1115       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1116       PetscFunctionReturn(PETSC_SUCCESS);
1117     }
1118     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1119     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1120       MatNullSpace nullsp, transnullsp;
1121 
1122       PetscCall(PetscViewerASCIIPushTab(viewer));
1123       PetscCall(MatGetSize(mat, &rows, &cols));
1124       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1125       if (rbs != 1 || cbs != 1) {
1126         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1127         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1128       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1129       if (mat->factortype) {
1130         MatSolverType solver;
1131         PetscCall(MatFactorGetSolverType(mat, &solver));
1132         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1133       }
1134       if (mat->ops->getinfo) {
1135         MatInfo info;
1136         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1137         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1138         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1139       }
1140       PetscCall(MatGetNullSpace(mat, &nullsp));
1141       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1142       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1143       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1144       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1145       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatProductView(mat, viewer));
1148       PetscCall(PetscViewerASCIIPopTab(viewer));
1149     }
1150   } else if (issaws) {
1151 #if defined(PETSC_HAVE_SAWS)
1152     PetscMPIInt rank;
1153 
1154     PetscCall(PetscObjectName((PetscObject)mat));
1155     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1156     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1157 #endif
1158   } else if (isstring) {
1159     const char *type;
1160     PetscCall(MatGetType(mat, &type));
1161     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1162     PetscTryTypeMethod(mat, view, viewer);
1163   }
1164   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1165     PetscCall(PetscViewerASCIIPushTab(viewer));
1166     PetscUseTypeMethod(mat, viewnative, viewer);
1167     PetscCall(PetscViewerASCIIPopTab(viewer));
1168   } else if (mat->ops->view) {
1169     PetscCall(PetscViewerASCIIPushTab(viewer));
1170     PetscUseTypeMethod(mat, view, viewer);
1171     PetscCall(PetscViewerASCIIPopTab(viewer));
1172   }
1173   if (isascii) {
1174     PetscCall(PetscViewerGetFormat(viewer, &format));
1175     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1176   }
1177   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178 #if !defined(PETSC_HAVE_THREADSAFETY)
1179   insidematview--;
1180 #endif
1181   PetscFunctionReturn(PETSC_SUCCESS);
1182 }
1183 
1184 #if defined(PETSC_USE_DEBUG)
1185   #include <../src/sys/totalview/tv_data_display.h>
1186 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1187 {
1188   TV_add_row("Local rows", "int", &mat->rmap->n);
1189   TV_add_row("Local columns", "int", &mat->cmap->n);
1190   TV_add_row("Global rows", "int", &mat->rmap->N);
1191   TV_add_row("Global columns", "int", &mat->cmap->N);
1192   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1193   return TV_format_OK;
1194 }
1195 #endif
1196 
1197 /*@C
1198   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1199   with `MatView()`.  The matrix format is determined from the options database.
1200   Generates a parallel MPI matrix if the communicator has more than one
1201   processor.  The default matrix type is `MATAIJ`.
1202 
1203   Collective
1204 
1205   Input Parameters:
1206 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1207             or some related function before a call to `MatLoad()`
1208 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1209 
1210   Options Database Keys:
1211    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1212    block size
1213 . -matload_block_size <bs> - set block size
1214 
1215   Level: beginner
1216 
1217   Notes:
1218   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1219   `Mat` before calling this routine if you wish to set it from the options database.
1220 
1221   `MatLoad()` automatically loads into the options database any options
1222   given in the file filename.info where filename is the name of the file
1223   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1224   file will be ignored if you use the -viewer_binary_skip_info option.
1225 
1226   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1227   sets the default matrix type AIJ and sets the local and global sizes.
1228   If type and/or size is already set, then the same are used.
1229 
1230   In parallel, each processor can load a subset of rows (or the
1231   entire matrix).  This routine is especially useful when a large
1232   matrix is stored on disk and only part of it is desired on each
1233   processor.  For example, a parallel solver may access only some of
1234   the rows from each processor.  The algorithm used here reads
1235   relatively small blocks of data rather than reading the entire
1236   matrix and then subsetting it.
1237 
1238   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1239   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1240   or the sequence like
1241 .vb
1242     `PetscViewer` v;
1243     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1244     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1245     `PetscViewerSetFromOptions`(v);
1246     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1247     `PetscViewerFileSetName`(v,"datafile");
1248 .ve
1249   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1250 $ -viewer_type {binary, hdf5}
1251 
1252   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1253   and src/mat/tutorials/ex10.c with the second approach.
1254 
1255   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1256   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1257   Multiple objects, both matrices and vectors, can be stored within the same file.
1258   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1259 
1260   Most users should not need to know the details of the binary storage
1261   format, since `MatLoad()` and `MatView()` completely hide these details.
1262   But for anyone who is interested, the standard binary matrix storage
1263   format is
1264 
1265 .vb
1266     PetscInt    MAT_FILE_CLASSID
1267     PetscInt    number of rows
1268     PetscInt    number of columns
1269     PetscInt    total number of nonzeros
1270     PetscInt    *number nonzeros in each row
1271     PetscInt    *column indices of all nonzeros (starting index is zero)
1272     PetscScalar *values of all nonzeros
1273 .ve
1274   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1275   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
1276   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1277 
1278   PETSc automatically does the byte swapping for
1279   machines that store the bytes reversed. Thus if you write your own binary
1280   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1281   and `PetscBinaryWrite()` to see how this may be done.
1282 
1283   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1284   Each processor's chunk is loaded independently by its owning MPI process.
1285   Multiple objects, both matrices and vectors, can be stored within the same file.
1286   They are looked up by their PetscObject name.
1287 
1288   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1289   by default the same structure and naming of the AIJ arrays and column count
1290   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1291 $    save example.mat A b -v7.3
1292   can be directly read by this routine (see Reference 1 for details).
1293 
1294   Depending on your MATLAB version, this format might be a default,
1295   otherwise you can set it as default in Preferences.
1296 
1297   Unless -nocompression flag is used to save the file in MATLAB,
1298   PETSc must be configured with ZLIB package.
1299 
1300   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1301 
1302   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1303 
1304   Corresponding `MatView()` is not yet implemented.
1305 
1306   The loaded matrix is actually a transpose of the original one in MATLAB,
1307   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1308   With this format, matrix is automatically transposed by PETSc,
1309   unless the matrix is marked as SPD or symmetric
1310   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1311 
1312   References:
1313 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1314 
1315 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1316  @*/
1317 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1318 {
1319   PetscBool flg;
1320 
1321   PetscFunctionBegin;
1322   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1323   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1324 
1325   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1326 
1327   flg = PETSC_FALSE;
1328   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1329   if (flg) {
1330     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1331     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1332   }
1333   flg = PETSC_FALSE;
1334   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1335   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1336 
1337   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1338   PetscUseTypeMethod(mat, load, viewer);
1339   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1340   PetscFunctionReturn(PETSC_SUCCESS);
1341 }
1342 
1343 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1344 {
1345   Mat_Redundant *redund = *redundant;
1346 
1347   PetscFunctionBegin;
1348   if (redund) {
1349     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1350       PetscCall(ISDestroy(&redund->isrow));
1351       PetscCall(ISDestroy(&redund->iscol));
1352       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1353     } else {
1354       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1355       PetscCall(PetscFree(redund->sbuf_j));
1356       PetscCall(PetscFree(redund->sbuf_a));
1357       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1358         PetscCall(PetscFree(redund->rbuf_j[i]));
1359         PetscCall(PetscFree(redund->rbuf_a[i]));
1360       }
1361       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1362     }
1363 
1364     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1365     PetscCall(PetscFree(redund));
1366   }
1367   PetscFunctionReturn(PETSC_SUCCESS);
1368 }
1369 
1370 /*@C
1371   MatDestroy - Frees space taken by a matrix.
1372 
1373   Collective
1374 
1375   Input Parameter:
1376 . A - the matrix
1377 
1378   Level: beginner
1379 
1380   Developer Notes:
1381   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1382   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1383   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1384   if changes are needed here.
1385 
1386 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1387 @*/
1388 PetscErrorCode MatDestroy(Mat *A)
1389 {
1390   PetscFunctionBegin;
1391   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1392   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1393   if (--((PetscObject)(*A))->refct > 0) {
1394     *A = NULL;
1395     PetscFunctionReturn(PETSC_SUCCESS);
1396   }
1397 
1398   /* if memory was published with SAWs then destroy it */
1399   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1400   PetscTryTypeMethod((*A), destroy);
1401 
1402   PetscCall(PetscFree((*A)->factorprefix));
1403   PetscCall(PetscFree((*A)->defaultvectype));
1404   PetscCall(PetscFree((*A)->defaultrandtype));
1405   PetscCall(PetscFree((*A)->bsizes));
1406   PetscCall(PetscFree((*A)->solvertype));
1407   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1408   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1409   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1410   PetscCall(MatProductClear(*A));
1411   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1413   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1414   PetscCall(MatDestroy(&(*A)->schur));
1415   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1416   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1417   PetscCall(PetscHeaderDestroy(A));
1418   PetscFunctionReturn(PETSC_SUCCESS);
1419 }
1420 
1421 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1422 /*@C
1423   MatSetValues - Inserts or adds a block of values into a matrix.
1424   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1425   MUST be called after all calls to `MatSetValues()` have been completed.
1426 
1427   Not Collective
1428 
1429   Input Parameters:
1430 + mat  - the matrix
1431 . v    - a logically two-dimensional array of values
1432 . m    - the number of rows
1433 . idxm - the global indices of the rows
1434 . n    - the number of columns
1435 . idxn - the global indices of the columns
1436 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1437 
1438   Level: beginner
1439 
1440   Notes:
1441   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1442 
1443   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1444   options cannot be mixed without intervening calls to the assembly
1445   routines.
1446 
1447   `MatSetValues()` uses 0-based row and column numbers in Fortran
1448   as well as in C.
1449 
1450   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1451   simply ignored. This allows easily inserting element stiffness matrices
1452   with homogeneous Dirichlet boundary conditions that you don't want represented
1453   in the matrix.
1454 
1455   Efficiency Alert:
1456   The routine `MatSetValuesBlocked()` may offer much better efficiency
1457   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1458 
1459   Developer Notes:
1460   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1461   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1462 
1463 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1464           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1465 @*/
1466 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1467 {
1468   PetscFunctionBeginHot;
1469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1470   PetscValidType(mat, 1);
1471   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1472   PetscValidIntPointer(idxm, 3);
1473   PetscValidIntPointer(idxn, 5);
1474   MatCheckPreallocated(mat, 1);
1475 
1476   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1477   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1478 
1479   if (PetscDefined(USE_DEBUG)) {
1480     PetscInt i, j;
1481 
1482     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1483     for (i = 0; i < m; i++) {
1484       for (j = 0; j < n; j++) {
1485         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1486 #if defined(PETSC_USE_COMPLEX)
1487           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]);
1488 #else
1489           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]);
1490 #endif
1491       }
1492     }
1493     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);
1494     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);
1495   }
1496 
1497   if (mat->assembled) {
1498     mat->was_assembled = PETSC_TRUE;
1499     mat->assembled     = PETSC_FALSE;
1500   }
1501   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1502   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1503   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1504   PetscFunctionReturn(PETSC_SUCCESS);
1505 }
1506 
1507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1508 /*@C
1509   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1510   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1511   MUST be called after all calls to `MatSetValues()` have been completed.
1512 
1513   Not Collective
1514 
1515   Input Parameters:
1516 + mat  - the matrix
1517 . v    - a logically two-dimensional array of values
1518 . ism  - the rows to provide
1519 . isn  - the columns to provide
1520 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1521 
1522   Level: beginner
1523 
1524   Notes:
1525   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1526 
1527   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1528   options cannot be mixed without intervening calls to the assembly
1529   routines.
1530 
1531   `MatSetValues()` uses 0-based row and column numbers in Fortran
1532   as well as in C.
1533 
1534   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1535   simply ignored. This allows easily inserting element stiffness matrices
1536   with homogeneous Dirichlet boundary conditions that you don't want represented
1537   in the matrix.
1538 
1539   Efficiency Alert:
1540   The routine `MatSetValuesBlocked()` may offer much better efficiency
1541   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1542 
1543   This is currently not optimized for any particular `ISType`
1544 
1545   Developer Notes:
1546   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1547   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1548 
1549 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1550           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1551 @*/
1552 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1553 {
1554   PetscInt        m, n;
1555   const PetscInt *rows, *cols;
1556 
1557   PetscFunctionBeginHot;
1558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1559   PetscCall(ISGetIndices(ism, &rows));
1560   PetscCall(ISGetIndices(isn, &cols));
1561   PetscCall(ISGetLocalSize(ism, &m));
1562   PetscCall(ISGetLocalSize(isn, &n));
1563   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1564   PetscCall(ISRestoreIndices(ism, &rows));
1565   PetscCall(ISRestoreIndices(isn, &cols));
1566   PetscFunctionReturn(PETSC_SUCCESS);
1567 }
1568 
1569 /*@
1570   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1571   values into a matrix
1572 
1573   Not Collective
1574 
1575   Input Parameters:
1576 + mat - the matrix
1577 . row - the (block) row to set
1578 - v   - a logically two-dimensional array of values
1579 
1580   Level: intermediate
1581 
1582   Notes:
1583   The values, `v`, are column-oriented (for the block version) and sorted
1584 
1585   All the nonzeros in the row must be provided
1586 
1587   The matrix must have previously had its column indices set, likely by having been assembled.
1588 
1589   The row must belong to this process
1590 
1591 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1592           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1593 @*/
1594 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1595 {
1596   PetscInt globalrow;
1597 
1598   PetscFunctionBegin;
1599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1600   PetscValidType(mat, 1);
1601   PetscValidScalarPointer(v, 3);
1602   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1603   PetscCall(MatSetValuesRow(mat, globalrow, v));
1604   PetscFunctionReturn(PETSC_SUCCESS);
1605 }
1606 
1607 /*@
1608   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1609   values into a matrix
1610 
1611   Not Collective
1612 
1613   Input Parameters:
1614 + mat - the matrix
1615 . row - the (block) row to set
1616 - 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
1617 
1618   Level: advanced
1619 
1620   Notes:
1621   The values, `v`, are column-oriented for the block version.
1622 
1623   All the nonzeros in the row must be provided
1624 
1625   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1626 
1627   The row must belong to this process
1628 
1629 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1630           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1631 @*/
1632 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1633 {
1634   PetscFunctionBeginHot;
1635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1636   PetscValidType(mat, 1);
1637   MatCheckPreallocated(mat, 1);
1638   PetscValidScalarPointer(v, 3);
1639   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1640   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1641   mat->insertmode = INSERT_VALUES;
1642 
1643   if (mat->assembled) {
1644     mat->was_assembled = PETSC_TRUE;
1645     mat->assembled     = PETSC_FALSE;
1646   }
1647   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1648   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1649   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1650   PetscFunctionReturn(PETSC_SUCCESS);
1651 }
1652 
1653 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1654 /*@
1655   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1656   Using structured grid indexing
1657 
1658   Not Collective
1659 
1660   Input Parameters:
1661 + mat  - the matrix
1662 . m    - number of rows being entered
1663 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1664 . n    - number of columns being entered
1665 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1666 . v    - a logically two-dimensional array of values
1667 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1668 
1669   Level: beginner
1670 
1671   Notes:
1672   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1673 
1674   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1675   options cannot be mixed without intervening calls to the assembly
1676   routines.
1677 
1678   The grid coordinates are across the entire grid, not just the local portion
1679 
1680   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1681   as well as in C.
1682 
1683   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1684 
1685   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1686   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1687 
1688   The columns and rows in the stencil passed in MUST be contained within the
1689   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1690   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1691   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1692   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1693 
1694   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1695   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1696   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1697   `DM_BOUNDARY_PERIODIC` boundary type.
1698 
1699   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
1700   a single value per point) you can skip filling those indices.
1701 
1702   Inspired by the structured grid interface to the HYPRE package
1703   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1704 
1705   Efficiency Alert:
1706   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1707   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1708 
1709   Fortran Notes:
1710   `idxm` and `idxn` should be declared as
1711 $     MatStencil idxm(4,m),idxn(4,n)
1712   and the values inserted using
1713 .vb
1714     idxm(MatStencil_i,1) = i
1715     idxm(MatStencil_j,1) = j
1716     idxm(MatStencil_k,1) = k
1717     idxm(MatStencil_c,1) = c
1718     etc
1719 .ve
1720 
1721 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1722           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1723 @*/
1724 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1725 {
1726   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1727   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1728   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1729 
1730   PetscFunctionBegin;
1731   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1733   PetscValidType(mat, 1);
1734   PetscValidPointer(idxm, 3);
1735   PetscValidPointer(idxn, 5);
1736 
1737   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1738     jdxm = buf;
1739     jdxn = buf + m;
1740   } else {
1741     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1742     jdxm = bufm;
1743     jdxn = bufn;
1744   }
1745   for (i = 0; i < m; i++) {
1746     for (j = 0; j < 3 - sdim; j++) dxm++;
1747     tmp = *dxm++ - starts[0];
1748     for (j = 0; j < dim - 1; j++) {
1749       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1750       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1751     }
1752     if (mat->stencil.noc) dxm++;
1753     jdxm[i] = tmp;
1754   }
1755   for (i = 0; i < n; i++) {
1756     for (j = 0; j < 3 - sdim; j++) dxn++;
1757     tmp = *dxn++ - starts[0];
1758     for (j = 0; j < dim - 1; j++) {
1759       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1760       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1761     }
1762     if (mat->stencil.noc) dxn++;
1763     jdxn[i] = tmp;
1764   }
1765   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1766   PetscCall(PetscFree2(bufm, bufn));
1767   PetscFunctionReturn(PETSC_SUCCESS);
1768 }
1769 
1770 /*@
1771   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1772   Using structured grid indexing
1773 
1774   Not Collective
1775 
1776   Input Parameters:
1777 + mat  - the matrix
1778 . m    - number of rows being entered
1779 . idxm - grid coordinates for matrix rows being entered
1780 . n    - number of columns being entered
1781 . idxn - grid coordinates for matrix columns being entered
1782 . v    - a logically two-dimensional array of values
1783 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1784 
1785   Level: beginner
1786 
1787   Notes:
1788   By default the values, `v`, are row-oriented and unsorted.
1789   See `MatSetOption()` for other options.
1790 
1791   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1792   options cannot be mixed without intervening calls to the assembly
1793   routines.
1794 
1795   The grid coordinates are across the entire grid, not just the local portion
1796 
1797   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1798   as well as in C.
1799 
1800   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1801 
1802   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1803   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1804 
1805   The columns and rows in the stencil passed in MUST be contained within the
1806   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1807   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1808   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1809   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1810 
1811   Negative indices may be passed in idxm and idxn, these rows and columns are
1812   simply ignored. This allows easily inserting element stiffness matrices
1813   with homogeneous Dirichlet boundary conditions that you don't want represented
1814   in the matrix.
1815 
1816   Inspired by the structured grid interface to the HYPRE package
1817   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1818 
1819   Fortran Notes:
1820   `idxm` and `idxn` should be declared as
1821 $     MatStencil idxm(4,m),idxn(4,n)
1822   and the values inserted using
1823 .vb
1824     idxm(MatStencil_i,1) = i
1825     idxm(MatStencil_j,1) = j
1826     idxm(MatStencil_k,1) = k
1827    etc
1828 .ve
1829 
1830 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1831           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1832           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1833 @*/
1834 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1835 {
1836   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1837   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1838   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1839 
1840   PetscFunctionBegin;
1841   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1843   PetscValidType(mat, 1);
1844   PetscValidPointer(idxm, 3);
1845   PetscValidPointer(idxn, 5);
1846   PetscValidScalarPointer(v, 6);
1847 
1848   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1849     jdxm = buf;
1850     jdxn = buf + m;
1851   } else {
1852     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1853     jdxm = bufm;
1854     jdxn = bufn;
1855   }
1856   for (i = 0; i < m; i++) {
1857     for (j = 0; j < 3 - sdim; j++) dxm++;
1858     tmp = *dxm++ - starts[0];
1859     for (j = 0; j < sdim - 1; j++) {
1860       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1861       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1862     }
1863     dxm++;
1864     jdxm[i] = tmp;
1865   }
1866   for (i = 0; i < n; i++) {
1867     for (j = 0; j < 3 - sdim; j++) dxn++;
1868     tmp = *dxn++ - starts[0];
1869     for (j = 0; j < sdim - 1; j++) {
1870       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1871       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1872     }
1873     dxn++;
1874     jdxn[i] = tmp;
1875   }
1876   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1877   PetscCall(PetscFree2(bufm, bufn));
1878   PetscFunctionReturn(PETSC_SUCCESS);
1879 }
1880 
1881 /*@
1882   MatSetStencil - Sets the grid information for setting values into a matrix via
1883   `MatSetValuesStencil()`
1884 
1885   Not Collective
1886 
1887   Input Parameters:
1888 + mat    - the matrix
1889 . dim    - dimension of the grid 1, 2, or 3
1890 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1891 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1892 - dof    - number of degrees of freedom per node
1893 
1894   Level: beginner
1895 
1896   Notes:
1897   Inspired by the structured grid interface to the HYPRE package
1898   (www.llnl.gov/CASC/hyper)
1899 
1900   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1901   user.
1902 
1903 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1904           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1905 @*/
1906 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1907 {
1908   PetscFunctionBegin;
1909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1910   PetscValidIntPointer(dims, 3);
1911   PetscValidIntPointer(starts, 4);
1912 
1913   mat->stencil.dim = dim + (dof > 1);
1914   for (PetscInt i = 0; i < dim; i++) {
1915     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1916     mat->stencil.starts[i] = starts[dim - i - 1];
1917   }
1918   mat->stencil.dims[dim]   = dof;
1919   mat->stencil.starts[dim] = 0;
1920   mat->stencil.noc         = (PetscBool)(dof == 1);
1921   PetscFunctionReturn(PETSC_SUCCESS);
1922 }
1923 
1924 /*@C
1925   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1926 
1927   Not Collective
1928 
1929   Input Parameters:
1930 + mat  - the matrix
1931 . v    - a logically two-dimensional array of values
1932 . m    - the number of block rows
1933 . idxm - the global block indices
1934 . n    - the number of block columns
1935 . idxn - the global block indices
1936 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1937 
1938   Level: intermediate
1939 
1940   Notes:
1941   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1942   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1943 
1944   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1945   NOT the total number of rows/columns; for example, if the block size is 2 and
1946   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1947   The values in idxm would be 1 2; that is the first index for each block divided by
1948   the block size.
1949 
1950   You must call `MatSetBlockSize()` when constructing this matrix (before
1951   preallocating it).
1952 
1953   By default the values, `v`, are row-oriented, so the layout of
1954   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1955 
1956   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1957   options cannot be mixed without intervening calls to the assembly
1958   routines.
1959 
1960   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1961   as well as in C.
1962 
1963   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1964   simply ignored. This allows easily inserting element stiffness matrices
1965   with homogeneous Dirichlet boundary conditions that you don't want represented
1966   in the matrix.
1967 
1968   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1969   internal searching must be done to determine where to place the
1970   data in the matrix storage space.  By instead inserting blocks of
1971   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1972   reduced.
1973 
1974   Example:
1975 .vb
1976    Suppose m=n=2 and block size(bs) = 2 The array is
1977 
1978    1  2  | 3  4
1979    5  6  | 7  8
1980    - - - | - - -
1981    9  10 | 11 12
1982    13 14 | 15 16
1983 
1984    v[] should be passed in like
1985    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1986 
1987   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1988    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1989 .ve
1990 
1991 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1992 @*/
1993 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1994 {
1995   PetscFunctionBeginHot;
1996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1997   PetscValidType(mat, 1);
1998   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1999   PetscValidIntPointer(idxm, 3);
2000   PetscValidIntPointer(idxn, 5);
2001   MatCheckPreallocated(mat, 1);
2002   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2003   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2004   if (PetscDefined(USE_DEBUG)) {
2005     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2006     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2007   }
2008   if (PetscDefined(USE_DEBUG)) {
2009     PetscInt rbs, cbs, M, N, i;
2010     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2011     PetscCall(MatGetSize(mat, &M, &N));
2012     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);
2013     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);
2014   }
2015   if (mat->assembled) {
2016     mat->was_assembled = PETSC_TRUE;
2017     mat->assembled     = PETSC_FALSE;
2018   }
2019   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2020   if (mat->ops->setvaluesblocked) {
2021     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2022   } else {
2023     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2024     PetscInt i, j, bs, cbs;
2025 
2026     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2027     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2028       iidxm = buf;
2029       iidxn = buf + m * bs;
2030     } else {
2031       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2032       iidxm = bufr;
2033       iidxn = bufc;
2034     }
2035     for (i = 0; i < m; i++) {
2036       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2037     }
2038     if (m != n || bs != cbs || idxm != idxn) {
2039       for (i = 0; i < n; i++) {
2040         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2041       }
2042     } else iidxn = iidxm;
2043     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2044     PetscCall(PetscFree2(bufr, bufc));
2045   }
2046   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2047   PetscFunctionReturn(PETSC_SUCCESS);
2048 }
2049 
2050 /*@C
2051   MatGetValues - Gets a block of local values from a matrix.
2052 
2053   Not Collective; can only return values that are owned by the give process
2054 
2055   Input Parameters:
2056 + mat  - the matrix
2057 . v    - a logically two-dimensional array for storing the values
2058 . m    - the number of rows
2059 . idxm - the  global indices of the rows
2060 . n    - the number of columns
2061 - idxn - the global indices of the columns
2062 
2063   Level: advanced
2064 
2065   Notes:
2066   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2067   The values, `v`, are then returned in a row-oriented format,
2068   analogous to that used by default in `MatSetValues()`.
2069 
2070   `MatGetValues()` uses 0-based row and column numbers in
2071   Fortran as well as in C.
2072 
2073   `MatGetValues()` requires that the matrix has been assembled
2074   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2075   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2076   without intermediate matrix assembly.
2077 
2078   Negative row or column indices will be ignored and those locations in `v` will be
2079   left unchanged.
2080 
2081   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2082   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2083   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2084 
2085 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2086 @*/
2087 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2088 {
2089   PetscFunctionBegin;
2090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2091   PetscValidType(mat, 1);
2092   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2093   PetscValidIntPointer(idxm, 3);
2094   PetscValidIntPointer(idxn, 5);
2095   PetscValidScalarPointer(v, 6);
2096   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2097   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2098   MatCheckPreallocated(mat, 1);
2099 
2100   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2101   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2102   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2103   PetscFunctionReturn(PETSC_SUCCESS);
2104 }
2105 
2106 /*@C
2107   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2108   defined previously by `MatSetLocalToGlobalMapping()`
2109 
2110   Not Collective
2111 
2112   Input Parameters:
2113 + mat  - the matrix
2114 . nrow - number of rows
2115 . irow - the row local indices
2116 . ncol - number of columns
2117 - icol - the column local indices
2118 
2119   Output Parameter:
2120 . y - a logically two-dimensional array of values
2121 
2122   Level: advanced
2123 
2124   Notes:
2125   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2126 
2127   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,
2128   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2129   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2130   with `MatSetLocalToGlobalMapping()`.
2131 
2132   Developer Notes:
2133   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2134   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2135 
2136 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2137           `MatSetValuesLocal()`, `MatGetValues()`
2138 @*/
2139 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2140 {
2141   PetscFunctionBeginHot;
2142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2143   PetscValidType(mat, 1);
2144   MatCheckPreallocated(mat, 1);
2145   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2146   PetscValidIntPointer(irow, 3);
2147   PetscValidIntPointer(icol, 5);
2148   if (PetscDefined(USE_DEBUG)) {
2149     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2150     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2151   }
2152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2153   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2154   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2155   else {
2156     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2157     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2158       irowm = buf;
2159       icolm = buf + nrow;
2160     } else {
2161       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2162       irowm = bufr;
2163       icolm = bufc;
2164     }
2165     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2166     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2167     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2168     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2169     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2170     PetscCall(PetscFree2(bufr, bufc));
2171   }
2172   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2173   PetscFunctionReturn(PETSC_SUCCESS);
2174 }
2175 
2176 /*@
2177   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2178   the same size. Currently, this can only be called once and creates the given matrix.
2179 
2180   Not Collective
2181 
2182   Input Parameters:
2183 + mat  - the matrix
2184 . nb   - the number of blocks
2185 . bs   - the number of rows (and columns) in each block
2186 . rows - a concatenation of the rows for each block
2187 - v    - a concatenation of logically two-dimensional arrays of values
2188 
2189   Level: advanced
2190 
2191   Note:
2192   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2193 
2194   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2195 
2196 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2197           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2198 @*/
2199 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2200 {
2201   PetscFunctionBegin;
2202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2203   PetscValidType(mat, 1);
2204   PetscValidIntPointer(rows, 4);
2205   PetscValidScalarPointer(v, 5);
2206   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2207 
2208   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2209   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2210   else {
2211     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2212   }
2213   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2214   PetscFunctionReturn(PETSC_SUCCESS);
2215 }
2216 
2217 /*@
2218   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2219   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2220   using a local (per-processor) numbering.
2221 
2222   Not Collective
2223 
2224   Input Parameters:
2225 + x        - the matrix
2226 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2227 - cmapping - column mapping
2228 
2229   Level: intermediate
2230 
2231   Note:
2232   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2233 
2234 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2235 @*/
2236 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2237 {
2238   PetscFunctionBegin;
2239   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2240   PetscValidType(x, 1);
2241   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2242   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2243   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2244   else {
2245     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2246     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2247   }
2248   PetscFunctionReturn(PETSC_SUCCESS);
2249 }
2250 
2251 /*@
2252   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2253 
2254   Not Collective
2255 
2256   Input Parameter:
2257 . A - the matrix
2258 
2259   Output Parameters:
2260 + rmapping - row mapping
2261 - cmapping - column mapping
2262 
2263   Level: advanced
2264 
2265 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2266 @*/
2267 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2268 {
2269   PetscFunctionBegin;
2270   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2271   PetscValidType(A, 1);
2272   if (rmapping) {
2273     PetscValidPointer(rmapping, 2);
2274     *rmapping = A->rmap->mapping;
2275   }
2276   if (cmapping) {
2277     PetscValidPointer(cmapping, 3);
2278     *cmapping = A->cmap->mapping;
2279   }
2280   PetscFunctionReturn(PETSC_SUCCESS);
2281 }
2282 
2283 /*@
2284   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2285 
2286   Logically Collective
2287 
2288   Input Parameters:
2289 + A    - the matrix
2290 . rmap - row layout
2291 - cmap - column layout
2292 
2293   Level: advanced
2294 
2295   Note:
2296   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2297 
2298 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2299 @*/
2300 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2301 {
2302   PetscFunctionBegin;
2303   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2304   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2305   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2306   PetscFunctionReturn(PETSC_SUCCESS);
2307 }
2308 
2309 /*@
2310   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2311 
2312   Not Collective
2313 
2314   Input Parameter:
2315 . A - the matrix
2316 
2317   Output Parameters:
2318 + rmap - row layout
2319 - cmap - column layout
2320 
2321   Level: advanced
2322 
2323 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2324 @*/
2325 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2326 {
2327   PetscFunctionBegin;
2328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2329   PetscValidType(A, 1);
2330   if (rmap) {
2331     PetscValidPointer(rmap, 2);
2332     *rmap = A->rmap;
2333   }
2334   if (cmap) {
2335     PetscValidPointer(cmap, 3);
2336     *cmap = A->cmap;
2337   }
2338   PetscFunctionReturn(PETSC_SUCCESS);
2339 }
2340 
2341 /*@C
2342   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2343   using a local numbering of the nodes.
2344 
2345   Not Collective
2346 
2347   Input Parameters:
2348 + mat  - the matrix
2349 . nrow - number of rows
2350 . irow - the row local indices
2351 . ncol - number of columns
2352 . icol - the column local indices
2353 . y    - a logically two-dimensional array of values
2354 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2355 
2356   Level: intermediate
2357 
2358   Notes:
2359   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2360   `MatSetUp()` before using this routine
2361 
2362   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2363 
2364   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2365   options cannot be mixed without intervening calls to the assembly
2366   routines.
2367 
2368   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2369   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2370 
2371   Developer Notes:
2372   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2373   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2374 
2375 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2376           `MatGetValuesLocal()`
2377 @*/
2378 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2379 {
2380   PetscFunctionBeginHot;
2381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2382   PetscValidType(mat, 1);
2383   MatCheckPreallocated(mat, 1);
2384   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2385   PetscValidIntPointer(irow, 3);
2386   PetscValidIntPointer(icol, 5);
2387   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2388   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2389   if (PetscDefined(USE_DEBUG)) {
2390     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2391     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2392   }
2393 
2394   if (mat->assembled) {
2395     mat->was_assembled = PETSC_TRUE;
2396     mat->assembled     = PETSC_FALSE;
2397   }
2398   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2399   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2400   else {
2401     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2402     const PetscInt *irowm, *icolm;
2403 
2404     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2405       bufr  = buf;
2406       bufc  = buf + nrow;
2407       irowm = bufr;
2408       icolm = bufc;
2409     } else {
2410       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2411       irowm = bufr;
2412       icolm = bufc;
2413     }
2414     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2415     else irowm = irow;
2416     if (mat->cmap->mapping) {
2417       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2418         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2419       } else icolm = irowm;
2420     } else icolm = icol;
2421     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2422     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2423   }
2424   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2425   PetscFunctionReturn(PETSC_SUCCESS);
2426 }
2427 
2428 /*@C
2429   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2430   using a local ordering of the nodes a block at a time.
2431 
2432   Not Collective
2433 
2434   Input Parameters:
2435 + mat  - the matrix
2436 . nrow - number of rows
2437 . irow - the row local indices
2438 . ncol - number of columns
2439 . icol - the column local indices
2440 . y    - a logically two-dimensional array of values
2441 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2442 
2443   Level: intermediate
2444 
2445   Notes:
2446   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2447   `MatSetUp()` before using this routine
2448 
2449   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2450   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2451 
2452   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2453   options cannot be mixed without intervening calls to the assembly
2454   routines.
2455 
2456   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2457   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2458 
2459   Developer Notes:
2460   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2461   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2462 
2463 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2464           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2465 @*/
2466 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2467 {
2468   PetscFunctionBeginHot;
2469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2470   PetscValidType(mat, 1);
2471   MatCheckPreallocated(mat, 1);
2472   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2473   PetscValidIntPointer(irow, 3);
2474   PetscValidIntPointer(icol, 5);
2475   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2476   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2477   if (PetscDefined(USE_DEBUG)) {
2478     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2479     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);
2480   }
2481 
2482   if (mat->assembled) {
2483     mat->was_assembled = PETSC_TRUE;
2484     mat->assembled     = PETSC_FALSE;
2485   }
2486   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2487     PetscInt irbs, rbs;
2488     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2489     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2490     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2491   }
2492   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2493     PetscInt icbs, cbs;
2494     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2495     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2496     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2497   }
2498   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2499   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2500   else {
2501     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2502     const PetscInt *irowm, *icolm;
2503 
2504     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2505       bufr  = buf;
2506       bufc  = buf + nrow;
2507       irowm = bufr;
2508       icolm = bufc;
2509     } else {
2510       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2511       irowm = bufr;
2512       icolm = bufc;
2513     }
2514     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2515     else irowm = irow;
2516     if (mat->cmap->mapping) {
2517       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2518         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2519       } else icolm = irowm;
2520     } else icolm = icol;
2521     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2522     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2523   }
2524   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2525   PetscFunctionReturn(PETSC_SUCCESS);
2526 }
2527 
2528 /*@
2529   MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2530 
2531   Collective
2532 
2533   Input Parameters:
2534 + mat - the matrix
2535 - x   - the vector to be multiplied
2536 
2537   Output Parameter:
2538 . y - the result
2539 
2540   Level: developer
2541 
2542   Note:
2543   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2544   call `MatMultDiagonalBlock`(A,y,y).
2545 
2546 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2547 @*/
2548 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2549 {
2550   PetscFunctionBegin;
2551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2552   PetscValidType(mat, 1);
2553   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2554   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2555 
2556   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2557   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2558   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2559   MatCheckPreallocated(mat, 1);
2560 
2561   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2562   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2563   PetscFunctionReturn(PETSC_SUCCESS);
2564 }
2565 
2566 /*@
2567   MatMult - Computes the matrix-vector product, y = Ax.
2568 
2569   Neighbor-wise Collective
2570 
2571   Input Parameters:
2572 + mat - the matrix
2573 - x   - the vector to be multiplied
2574 
2575   Output Parameter:
2576 . y - the result
2577 
2578   Level: beginner
2579 
2580   Note:
2581   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2582   call `MatMult`(A,y,y).
2583 
2584 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2585 @*/
2586 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2587 {
2588   PetscFunctionBegin;
2589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2590   PetscValidType(mat, 1);
2591   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2592   VecCheckAssembled(x);
2593   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2595   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2596   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2597   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);
2598   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);
2599   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);
2600   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);
2601   PetscCall(VecSetErrorIfLocked(y, 3));
2602   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2603   MatCheckPreallocated(mat, 1);
2604 
2605   PetscCall(VecLockReadPush(x));
2606   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2607   PetscUseTypeMethod(mat, mult, x, y);
2608   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2609   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2610   PetscCall(VecLockReadPop(x));
2611   PetscFunctionReturn(PETSC_SUCCESS);
2612 }
2613 
2614 /*@
2615   MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2616 
2617   Neighbor-wise Collective
2618 
2619   Input Parameters:
2620 + mat - the matrix
2621 - x   - the vector to be multiplied
2622 
2623   Output Parameter:
2624 . y - the result
2625 
2626   Level: beginner
2627 
2628   Notes:
2629   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2630   call `MatMultTranspose`(A,y,y).
2631 
2632   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2633   use `MatMultHermitianTranspose()`
2634 
2635 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2636 @*/
2637 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2638 {
2639   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2640 
2641   PetscFunctionBegin;
2642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2643   PetscValidType(mat, 1);
2644   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2645   VecCheckAssembled(x);
2646   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2647 
2648   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2649   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2650   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2651   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);
2652   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);
2653   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);
2654   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);
2655   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2656   MatCheckPreallocated(mat, 1);
2657 
2658   if (!mat->ops->multtranspose) {
2659     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2660     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);
2661   } else op = mat->ops->multtranspose;
2662   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2663   PetscCall(VecLockReadPush(x));
2664   PetscCall((*op)(mat, x, y));
2665   PetscCall(VecLockReadPop(x));
2666   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2667   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2668   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2669   PetscFunctionReturn(PETSC_SUCCESS);
2670 }
2671 
2672 /*@
2673   MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2674 
2675   Neighbor-wise Collective
2676 
2677   Input Parameters:
2678 + mat - the matrix
2679 - x   - the vector to be multiplied
2680 
2681   Output Parameter:
2682 . y - the result
2683 
2684   Level: beginner
2685 
2686   Notes:
2687   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2688   call `MatMultHermitianTranspose`(A,y,y).
2689 
2690   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2691 
2692   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2693 
2694 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2695 @*/
2696 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2697 {
2698   PetscFunctionBegin;
2699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2700   PetscValidType(mat, 1);
2701   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2702   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2703 
2704   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2705   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2706   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2707   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);
2708   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);
2709   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);
2710   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);
2711   MatCheckPreallocated(mat, 1);
2712 
2713   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2714 #if defined(PETSC_USE_COMPLEX)
2715   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2716     PetscCall(VecLockReadPush(x));
2717     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2718     else PetscUseTypeMethod(mat, mult, x, y);
2719     PetscCall(VecLockReadPop(x));
2720   } else {
2721     Vec w;
2722     PetscCall(VecDuplicate(x, &w));
2723     PetscCall(VecCopy(x, w));
2724     PetscCall(VecConjugate(w));
2725     PetscCall(MatMultTranspose(mat, w, y));
2726     PetscCall(VecDestroy(&w));
2727     PetscCall(VecConjugate(y));
2728   }
2729   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2730 #else
2731   PetscCall(MatMultTranspose(mat, x, y));
2732 #endif
2733   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2734   PetscFunctionReturn(PETSC_SUCCESS);
2735 }
2736 
2737 /*@
2738   MatMultAdd -  Computes v3 = v2 + A * v1.
2739 
2740   Neighbor-wise Collective
2741 
2742   Input Parameters:
2743 + mat - the matrix
2744 . v1  - the vector to be multiplied by `mat`
2745 - v2  - the vector to be added to the result
2746 
2747   Output Parameter:
2748 . v3 - the result
2749 
2750   Level: beginner
2751 
2752   Note:
2753   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2754   call `MatMultAdd`(A,v1,v2,v1).
2755 
2756 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2757 @*/
2758 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2759 {
2760   PetscFunctionBegin;
2761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2762   PetscValidType(mat, 1);
2763   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2764   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2765   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2766 
2767   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2768   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2769   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);
2770   /* 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);
2771      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); */
2772   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);
2773   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);
2774   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2775   MatCheckPreallocated(mat, 1);
2776 
2777   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2778   PetscCall(VecLockReadPush(v1));
2779   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2780   PetscCall(VecLockReadPop(v1));
2781   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2782   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2783   PetscFunctionReturn(PETSC_SUCCESS);
2784 }
2785 
2786 /*@
2787   MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2788 
2789   Neighbor-wise Collective
2790 
2791   Input Parameters:
2792 + mat - the matrix
2793 . v1  - the vector to be multiplied by the transpose of the matrix
2794 - v2  - the vector to be added to the result
2795 
2796   Output Parameter:
2797 . v3 - the result
2798 
2799   Level: beginner
2800 
2801   Note:
2802   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2803   call `MatMultTransposeAdd`(A,v1,v2,v1).
2804 
2805 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2806 @*/
2807 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2808 {
2809   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2810 
2811   PetscFunctionBegin;
2812   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2813   PetscValidType(mat, 1);
2814   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2815   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2816   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2817 
2818   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2819   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2820   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);
2821   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);
2822   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);
2823   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2824   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2825   MatCheckPreallocated(mat, 1);
2826 
2827   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2828   PetscCall(VecLockReadPush(v1));
2829   PetscCall((*op)(mat, v1, v2, v3));
2830   PetscCall(VecLockReadPop(v1));
2831   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2832   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2833   PetscFunctionReturn(PETSC_SUCCESS);
2834 }
2835 
2836 /*@
2837   MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2838 
2839   Neighbor-wise Collective
2840 
2841   Input Parameters:
2842 + mat - the matrix
2843 . v1  - the vector to be multiplied by the Hermitian transpose
2844 - v2  - the vector to be added to the result
2845 
2846   Output Parameter:
2847 . v3 - the result
2848 
2849   Level: beginner
2850 
2851   Note:
2852   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2853   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2854 
2855 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2856 @*/
2857 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2858 {
2859   PetscFunctionBegin;
2860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2861   PetscValidType(mat, 1);
2862   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2863   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2864   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2865 
2866   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2867   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2868   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2869   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);
2870   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);
2871   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);
2872   MatCheckPreallocated(mat, 1);
2873 
2874   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2875   PetscCall(VecLockReadPush(v1));
2876   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2877   else {
2878     Vec w, z;
2879     PetscCall(VecDuplicate(v1, &w));
2880     PetscCall(VecCopy(v1, w));
2881     PetscCall(VecConjugate(w));
2882     PetscCall(VecDuplicate(v3, &z));
2883     PetscCall(MatMultTranspose(mat, w, z));
2884     PetscCall(VecDestroy(&w));
2885     PetscCall(VecConjugate(z));
2886     if (v2 != v3) {
2887       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2888     } else {
2889       PetscCall(VecAXPY(v3, 1.0, z));
2890     }
2891     PetscCall(VecDestroy(&z));
2892   }
2893   PetscCall(VecLockReadPop(v1));
2894   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2895   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2896   PetscFunctionReturn(PETSC_SUCCESS);
2897 }
2898 
2899 /*@C
2900   MatGetFactorType - gets the type of factorization it is
2901 
2902   Not Collective
2903 
2904   Input Parameter:
2905 . mat - the matrix
2906 
2907   Output Parameter:
2908 . 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`
2909 
2910   Level: intermediate
2911 
2912 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2913           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2914 @*/
2915 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2916 {
2917   PetscFunctionBegin;
2918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2919   PetscValidType(mat, 1);
2920   PetscValidPointer(t, 2);
2921   *t = mat->factortype;
2922   PetscFunctionReturn(PETSC_SUCCESS);
2923 }
2924 
2925 /*@C
2926   MatSetFactorType - sets the type of factorization it is
2927 
2928   Logically Collective
2929 
2930   Input Parameters:
2931 + mat - the matrix
2932 - 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`
2933 
2934   Level: intermediate
2935 
2936 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2937           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2938 @*/
2939 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2940 {
2941   PetscFunctionBegin;
2942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2943   PetscValidType(mat, 1);
2944   mat->factortype = t;
2945   PetscFunctionReturn(PETSC_SUCCESS);
2946 }
2947 
2948 /*@C
2949   MatGetInfo - Returns information about matrix storage (number of
2950   nonzeros, memory, etc.).
2951 
2952   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2953 
2954   Input Parameters:
2955 + mat  - the matrix
2956 - 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)
2957 
2958   Output Parameter:
2959 . info - matrix information context
2960 
2961   Options Database Key:
2962 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2963 
2964   Notes:
2965   The `MatInfo` context contains a variety of matrix data, including
2966   number of nonzeros allocated and used, number of mallocs during
2967   matrix assembly, etc.  Additional information for factored matrices
2968   is provided (such as the fill ratio, number of mallocs during
2969   factorization, etc.).
2970 
2971   Example:
2972   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2973   data within the MatInfo context.  For example,
2974 .vb
2975       MatInfo info;
2976       Mat     A;
2977       double  mal, nz_a, nz_u;
2978 
2979       MatGetInfo(A, MAT_LOCAL, &info);
2980       mal  = info.mallocs;
2981       nz_a = info.nz_allocated;
2982 .ve
2983 
2984   Fortran users should declare info as a double precision
2985   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2986   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2987   a complete list of parameter names.
2988 .vb
2989       double  precision info(MAT_INFO_SIZE)
2990       double  precision mal, nz_a
2991       Mat     A
2992       integer ierr
2993 
2994       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2995       mal = info(MAT_INFO_MALLOCS)
2996       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2997 .ve
2998 
2999   Level: intermediate
3000 
3001   Developer Notes:
3002   The Fortran interface is not autogenerated as the
3003   interface definition cannot be generated correctly [due to `MatInfo` argument]
3004 
3005 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3006 @*/
3007 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3008 {
3009   PetscFunctionBegin;
3010   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3011   PetscValidType(mat, 1);
3012   PetscValidPointer(info, 3);
3013   MatCheckPreallocated(mat, 1);
3014   PetscUseTypeMethod(mat, getinfo, flag, info);
3015   PetscFunctionReturn(PETSC_SUCCESS);
3016 }
3017 
3018 /*
3019    This is used by external packages where it is not easy to get the info from the actual
3020    matrix factorization.
3021 */
3022 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3023 {
3024   PetscFunctionBegin;
3025   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3026   PetscFunctionReturn(PETSC_SUCCESS);
3027 }
3028 
3029 /*@C
3030   MatLUFactor - Performs in-place LU factorization of matrix.
3031 
3032   Collective
3033 
3034   Input Parameters:
3035 + mat  - the matrix
3036 . row  - row permutation
3037 . col  - column permutation
3038 - info - options for factorization, includes
3039 .vb
3040           fill - expected fill as ratio of original fill.
3041           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3042                    Run with the option -info to determine an optimal value to use
3043 .ve
3044 
3045   Level: developer
3046 
3047   Notes:
3048   Most users should employ the `KSP` interface for linear solvers
3049   instead of working directly with matrix algebra routines such as this.
3050   See, e.g., `KSPCreate()`.
3051 
3052   This changes the state of the matrix to a factored matrix; it cannot be used
3053   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3054 
3055   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3056   when not using `KSP`.
3057 
3058   Developer Notes:
3059   The Fortran interface is not autogenerated as the
3060   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3061 
3062 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3063           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3064 @*/
3065 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3066 {
3067   MatFactorInfo tinfo;
3068 
3069   PetscFunctionBegin;
3070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3071   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3072   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3073   if (info) PetscValidPointer(info, 4);
3074   PetscValidType(mat, 1);
3075   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3076   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3077   MatCheckPreallocated(mat, 1);
3078   if (!info) {
3079     PetscCall(MatFactorInfoInitialize(&tinfo));
3080     info = &tinfo;
3081   }
3082 
3083   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3084   PetscUseTypeMethod(mat, lufactor, row, col, info);
3085   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3086   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3087   PetscFunctionReturn(PETSC_SUCCESS);
3088 }
3089 
3090 /*@C
3091   MatILUFactor - Performs in-place ILU factorization of matrix.
3092 
3093   Collective
3094 
3095   Input Parameters:
3096 + mat  - the matrix
3097 . row  - row permutation
3098 . col  - column permutation
3099 - info - structure containing
3100 .vb
3101       levels - number of levels of fill.
3102       expected fill - as ratio of original fill.
3103       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3104                 missing diagonal entries)
3105 .ve
3106 
3107   Level: developer
3108 
3109   Notes:
3110   Most users should employ the `KSP` interface for linear solvers
3111   instead of working directly with matrix algebra routines such as this.
3112   See, e.g., `KSPCreate()`.
3113 
3114   Probably really in-place only when level of fill is zero, otherwise allocates
3115   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3116   when not using `KSP`.
3117 
3118   Developer Notes:
3119   The Fortran interface is not autogenerated as the
3120   interface definition cannot be generated correctly [due to MatFactorInfo]
3121 
3122 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3123 @*/
3124 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3125 {
3126   PetscFunctionBegin;
3127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3128   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3129   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3130   PetscValidPointer(info, 4);
3131   PetscValidType(mat, 1);
3132   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3133   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3134   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3135   MatCheckPreallocated(mat, 1);
3136 
3137   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3138   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3139   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3140   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3141   PetscFunctionReturn(PETSC_SUCCESS);
3142 }
3143 
3144 /*@C
3145   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3146   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3147 
3148   Collective
3149 
3150   Input Parameters:
3151 + fact - the factor matrix obtained with `MatGetFactor()`
3152 . mat  - the matrix
3153 . row  - the row permutation
3154 . col  - the column permutation
3155 - info - options for factorization, includes
3156 .vb
3157           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3158           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3159 .ve
3160 
3161   Level: developer
3162 
3163   Notes:
3164   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3165 
3166   Most users should employ the simplified `KSP` interface for linear solvers
3167   instead of working directly with matrix algebra routines such as this.
3168   See, e.g., `KSPCreate()`.
3169 
3170   Developer Notes:
3171   The Fortran interface is not autogenerated as the
3172   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3173 
3174 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3175 @*/
3176 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3177 {
3178   MatFactorInfo tinfo;
3179 
3180   PetscFunctionBegin;
3181   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3183   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3184   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3185   if (info) PetscValidPointer(info, 5);
3186   PetscValidType(fact, 1);
3187   PetscValidType(mat, 2);
3188   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3189   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3190   MatCheckPreallocated(mat, 2);
3191   if (!info) {
3192     PetscCall(MatFactorInfoInitialize(&tinfo));
3193     info = &tinfo;
3194   }
3195 
3196   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3197   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3198   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3199   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3200   PetscFunctionReturn(PETSC_SUCCESS);
3201 }
3202 
3203 /*@C
3204   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3205   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3206 
3207   Collective
3208 
3209   Input Parameters:
3210 + fact - the factor matrix obtained with `MatGetFactor()`
3211 . mat  - the matrix
3212 - info - options for factorization
3213 
3214   Level: developer
3215 
3216   Notes:
3217   See `MatLUFactor()` for in-place factorization.  See
3218   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3219 
3220   Most users should employ the `KSP` interface for linear solvers
3221   instead of working directly with matrix algebra routines such as this.
3222   See, e.g., `KSPCreate()`.
3223 
3224   Developer Notes:
3225   The Fortran interface is not autogenerated as the
3226   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3227 
3228 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3229 @*/
3230 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3231 {
3232   MatFactorInfo tinfo;
3233 
3234   PetscFunctionBegin;
3235   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3237   PetscValidType(fact, 1);
3238   PetscValidType(mat, 2);
3239   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3240   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,
3241              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3242 
3243   MatCheckPreallocated(mat, 2);
3244   if (!info) {
3245     PetscCall(MatFactorInfoInitialize(&tinfo));
3246     info = &tinfo;
3247   }
3248 
3249   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3250   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3251   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3252   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3253   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3254   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3255   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3256   PetscFunctionReturn(PETSC_SUCCESS);
3257 }
3258 
3259 /*@C
3260   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3261   symmetric matrix.
3262 
3263   Collective
3264 
3265   Input Parameters:
3266 + mat  - the matrix
3267 . perm - row and column permutations
3268 - info - expected fill as ratio of original fill
3269 
3270   Level: developer
3271 
3272   Notes:
3273   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3274   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3275 
3276   Most users should employ the `KSP` interface for linear solvers
3277   instead of working directly with matrix algebra routines such as this.
3278   See, e.g., `KSPCreate()`.
3279 
3280   Developer Notes:
3281   The Fortran interface is not autogenerated as the
3282   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3283 
3284 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3285           `MatGetOrdering()`
3286 @*/
3287 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3288 {
3289   MatFactorInfo tinfo;
3290 
3291   PetscFunctionBegin;
3292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3293   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3294   if (info) PetscValidPointer(info, 3);
3295   PetscValidType(mat, 1);
3296   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3297   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3298   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3299   MatCheckPreallocated(mat, 1);
3300   if (!info) {
3301     PetscCall(MatFactorInfoInitialize(&tinfo));
3302     info = &tinfo;
3303   }
3304 
3305   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3306   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3307   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3308   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3309   PetscFunctionReturn(PETSC_SUCCESS);
3310 }
3311 
3312 /*@C
3313   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3314   of a symmetric matrix.
3315 
3316   Collective
3317 
3318   Input Parameters:
3319 + fact - the factor matrix obtained with `MatGetFactor()`
3320 . mat  - the matrix
3321 . perm - row and column permutations
3322 - info - options for factorization, includes
3323 .vb
3324           fill - expected fill as ratio of original fill.
3325           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3326                    Run with the option -info to determine an optimal value to use
3327 .ve
3328 
3329   Level: developer
3330 
3331   Notes:
3332   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3333   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3334 
3335   Most users should employ the `KSP` interface for linear solvers
3336   instead of working directly with matrix algebra routines such as this.
3337   See, e.g., `KSPCreate()`.
3338 
3339   Developer Notes:
3340   The Fortran interface is not autogenerated as the
3341   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3342 
3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3344           `MatGetOrdering()`
3345 @*/
3346 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3347 {
3348   MatFactorInfo tinfo;
3349 
3350   PetscFunctionBegin;
3351   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3353   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3354   if (info) PetscValidPointer(info, 4);
3355   PetscValidType(fact, 1);
3356   PetscValidType(mat, 2);
3357   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3358   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3359   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3360   MatCheckPreallocated(mat, 2);
3361   if (!info) {
3362     PetscCall(MatFactorInfoInitialize(&tinfo));
3363     info = &tinfo;
3364   }
3365 
3366   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3367   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3368   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3369   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3370   PetscFunctionReturn(PETSC_SUCCESS);
3371 }
3372 
3373 /*@C
3374   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3375   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3376   `MatCholeskyFactorSymbolic()`.
3377 
3378   Collective
3379 
3380   Input Parameters:
3381 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3382 . mat  - the initial matrix that is to be factored
3383 - info - options for factorization
3384 
3385   Level: developer
3386 
3387   Note:
3388   Most users should employ the `KSP` interface for linear solvers
3389   instead of working directly with matrix algebra routines such as this.
3390   See, e.g., `KSPCreate()`.
3391 
3392   Developer Notes:
3393   The Fortran interface is not autogenerated as the
3394   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3395 
3396 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3397 @*/
3398 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3399 {
3400   MatFactorInfo tinfo;
3401 
3402   PetscFunctionBegin;
3403   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3405   PetscValidType(fact, 1);
3406   PetscValidType(mat, 2);
3407   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3408   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,
3409              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3410   MatCheckPreallocated(mat, 2);
3411   if (!info) {
3412     PetscCall(MatFactorInfoInitialize(&tinfo));
3413     info = &tinfo;
3414   }
3415 
3416   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3417   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3418   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3419   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3420   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3421   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3422   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3423   PetscFunctionReturn(PETSC_SUCCESS);
3424 }
3425 
3426 /*@
3427   MatQRFactor - Performs in-place QR factorization of matrix.
3428 
3429   Collective
3430 
3431   Input Parameters:
3432 + mat  - the matrix
3433 . col  - column permutation
3434 - info - options for factorization, includes
3435 .vb
3436           fill - expected fill as ratio of original fill.
3437           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3438                    Run with the option -info to determine an optimal value to use
3439 .ve
3440 
3441   Level: developer
3442 
3443   Notes:
3444   Most users should employ the `KSP` interface for linear solvers
3445   instead of working directly with matrix algebra routines such as this.
3446   See, e.g., `KSPCreate()`.
3447 
3448   This changes the state of the matrix to a factored matrix; it cannot be used
3449   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3450 
3451   Developer Notes:
3452   The Fortran interface is not autogenerated as the
3453   interface definition cannot be generated correctly [due to MatFactorInfo]
3454 
3455 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3456           `MatSetUnfactored()`
3457 @*/
3458 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3459 {
3460   PetscFunctionBegin;
3461   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3462   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3463   if (info) PetscValidPointer(info, 3);
3464   PetscValidType(mat, 1);
3465   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3466   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3467   MatCheckPreallocated(mat, 1);
3468   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3469   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3470   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3471   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3472   PetscFunctionReturn(PETSC_SUCCESS);
3473 }
3474 
3475 /*@
3476   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3477   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3478 
3479   Collective
3480 
3481   Input Parameters:
3482 + fact - the factor matrix obtained with `MatGetFactor()`
3483 . mat  - the matrix
3484 . col  - column permutation
3485 - info - options for factorization, includes
3486 .vb
3487           fill - expected fill as ratio of original fill.
3488           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3489                    Run with the option -info to determine an optimal value to use
3490 .ve
3491 
3492   Level: developer
3493 
3494   Note:
3495   Most users should employ the `KSP` interface for linear solvers
3496   instead of working directly with matrix algebra routines such as this.
3497   See, e.g., `KSPCreate()`.
3498 
3499   Developer Notes:
3500   The Fortran interface is not autogenerated as the
3501   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3502 
3503 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3504 @*/
3505 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3506 {
3507   MatFactorInfo tinfo;
3508 
3509   PetscFunctionBegin;
3510   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3511   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3512   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3513   if (info) PetscValidPointer(info, 4);
3514   PetscValidType(fact, 1);
3515   PetscValidType(mat, 2);
3516   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3517   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3518   MatCheckPreallocated(mat, 2);
3519   if (!info) {
3520     PetscCall(MatFactorInfoInitialize(&tinfo));
3521     info = &tinfo;
3522   }
3523 
3524   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3525   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3526   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3527   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3528   PetscFunctionReturn(PETSC_SUCCESS);
3529 }
3530 
3531 /*@
3532   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3533   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3534 
3535   Collective
3536 
3537   Input Parameters:
3538 + fact - the factor matrix obtained with `MatGetFactor()`
3539 . mat  - the matrix
3540 - info - options for factorization
3541 
3542   Level: developer
3543 
3544   Notes:
3545   See `MatQRFactor()` for in-place factorization.
3546 
3547   Most users should employ the `KSP` interface for linear solvers
3548   instead of working directly with matrix algebra routines such as this.
3549   See, e.g., `KSPCreate()`.
3550 
3551   Developer Notes:
3552   The Fortran interface is not autogenerated as the
3553   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3554 
3555 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3556 @*/
3557 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3558 {
3559   MatFactorInfo tinfo;
3560 
3561   PetscFunctionBegin;
3562   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3564   PetscValidType(fact, 1);
3565   PetscValidType(mat, 2);
3566   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3567   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,
3568              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3569 
3570   MatCheckPreallocated(mat, 2);
3571   if (!info) {
3572     PetscCall(MatFactorInfoInitialize(&tinfo));
3573     info = &tinfo;
3574   }
3575 
3576   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3577   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3578   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3579   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3580   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3581   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3582   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3583   PetscFunctionReturn(PETSC_SUCCESS);
3584 }
3585 
3586 /*@
3587   MatSolve - Solves A x = b, given a factored matrix.
3588 
3589   Neighbor-wise Collective
3590 
3591   Input Parameters:
3592 + mat - the factored matrix
3593 - b   - the right-hand-side vector
3594 
3595   Output Parameter:
3596 . x - the result vector
3597 
3598   Level: developer
3599 
3600   Notes:
3601   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3602   call `MatSolve`(A,x,x).
3603 
3604   Most users should employ the `KSP` interface for linear solvers
3605   instead of working directly with matrix algebra routines such as this.
3606   See, e.g., `KSPCreate()`.
3607 
3608 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3609 @*/
3610 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3611 {
3612   PetscFunctionBegin;
3613   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3614   PetscValidType(mat, 1);
3615   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3616   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3617   PetscCheckSameComm(mat, 1, b, 2);
3618   PetscCheckSameComm(mat, 1, x, 3);
3619   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3620   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);
3621   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);
3622   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);
3623   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3624   MatCheckPreallocated(mat, 1);
3625 
3626   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3627   if (mat->factorerrortype) {
3628     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3629     PetscCall(VecSetInf(x));
3630   } else PetscUseTypeMethod(mat, solve, b, x);
3631   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3632   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3633   PetscFunctionReturn(PETSC_SUCCESS);
3634 }
3635 
3636 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3637 {
3638   Vec      b, x;
3639   PetscInt N, i;
3640   PetscErrorCode (*f)(Mat, Vec, Vec);
3641   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3642 
3643   PetscFunctionBegin;
3644   if (A->factorerrortype) {
3645     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3646     PetscCall(MatSetInf(X));
3647     PetscFunctionReturn(PETSC_SUCCESS);
3648   }
3649   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3650   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3651   PetscCall(MatBoundToCPU(A, &Abound));
3652   if (!Abound) {
3653     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3654     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3655   }
3656 #if PetscDefined(HAVE_CUDA)
3657   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3658   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3659 #elif PetscDefined(HAVE_HIP)
3660   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3661   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3662 #endif
3663   PetscCall(MatGetSize(B, NULL, &N));
3664   for (i = 0; i < N; i++) {
3665     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3666     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3667     PetscCall((*f)(A, b, x));
3668     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3669     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3670   }
3671   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3672   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3673   PetscFunctionReturn(PETSC_SUCCESS);
3674 }
3675 
3676 /*@
3677   MatMatSolve - Solves A X = B, given a factored matrix.
3678 
3679   Neighbor-wise Collective
3680 
3681   Input Parameters:
3682 + A - the factored matrix
3683 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3684 
3685   Output Parameter:
3686 . X - the result matrix (dense matrix)
3687 
3688   Level: developer
3689 
3690   Note:
3691   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3692   otherwise, `B` and `X` cannot be the same.
3693 
3694 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3695 @*/
3696 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3697 {
3698   PetscFunctionBegin;
3699   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3700   PetscValidType(A, 1);
3701   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3702   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3703   PetscCheckSameComm(A, 1, B, 2);
3704   PetscCheckSameComm(A, 1, X, 3);
3705   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);
3706   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);
3707   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");
3708   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3709   MatCheckPreallocated(A, 1);
3710 
3711   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3712   if (!A->ops->matsolve) {
3713     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3714     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3715   } else PetscUseTypeMethod(A, matsolve, B, X);
3716   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3717   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3718   PetscFunctionReturn(PETSC_SUCCESS);
3719 }
3720 
3721 /*@
3722   MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3723 
3724   Neighbor-wise Collective
3725 
3726   Input Parameters:
3727 + A - the factored matrix
3728 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3729 
3730   Output Parameter:
3731 . X - the result matrix (dense matrix)
3732 
3733   Level: developer
3734 
3735   Note:
3736   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3737   call `MatMatSolveTranspose`(A,X,X).
3738 
3739 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3740 @*/
3741 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3742 {
3743   PetscFunctionBegin;
3744   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3745   PetscValidType(A, 1);
3746   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3747   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3748   PetscCheckSameComm(A, 1, B, 2);
3749   PetscCheckSameComm(A, 1, X, 3);
3750   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3751   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);
3752   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);
3753   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);
3754   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");
3755   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3756   MatCheckPreallocated(A, 1);
3757 
3758   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3759   if (!A->ops->matsolvetranspose) {
3760     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3761     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3762   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3763   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3764   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3765   PetscFunctionReturn(PETSC_SUCCESS);
3766 }
3767 
3768 /*@
3769   MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3770 
3771   Neighbor-wise Collective
3772 
3773   Input Parameters:
3774 + A  - the factored matrix
3775 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3776 
3777   Output Parameter:
3778 . X - the result matrix (dense matrix)
3779 
3780   Level: developer
3781 
3782   Note:
3783   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3784   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3785 
3786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3787 @*/
3788 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3789 {
3790   PetscFunctionBegin;
3791   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3792   PetscValidType(A, 1);
3793   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3794   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3795   PetscCheckSameComm(A, 1, Bt, 2);
3796   PetscCheckSameComm(A, 1, X, 3);
3797 
3798   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3799   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);
3800   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);
3801   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");
3802   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3803   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3804   MatCheckPreallocated(A, 1);
3805 
3806   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3807   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3808   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3809   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3810   PetscFunctionReturn(PETSC_SUCCESS);
3811 }
3812 
3813 /*@
3814   MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3815   U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3816 
3817   Neighbor-wise Collective
3818 
3819   Input Parameters:
3820 + mat - the factored matrix
3821 - b   - the right-hand-side vector
3822 
3823   Output Parameter:
3824 . x - the result vector
3825 
3826   Level: developer
3827 
3828   Notes:
3829   `MatSolve()` should be used for most applications, as it performs
3830   a forward solve followed by a backward solve.
3831 
3832   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3833   call `MatForwardSolve`(A,x,x).
3834 
3835   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3836   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3837   `MatForwardSolve()` solves U^T*D y = b, and
3838   `MatBackwardSolve()` solves U x = y.
3839   Thus they do not provide a symmetric preconditioner.
3840 
3841 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3842 @*/
3843 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3844 {
3845   PetscFunctionBegin;
3846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3847   PetscValidType(mat, 1);
3848   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3849   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3850   PetscCheckSameComm(mat, 1, b, 2);
3851   PetscCheckSameComm(mat, 1, x, 3);
3852   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3853   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);
3854   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);
3855   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);
3856   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3857   MatCheckPreallocated(mat, 1);
3858 
3859   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3860   PetscUseTypeMethod(mat, forwardsolve, b, x);
3861   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3862   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3863   PetscFunctionReturn(PETSC_SUCCESS);
3864 }
3865 
3866 /*@
3867   MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3868   D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3869 
3870   Neighbor-wise Collective
3871 
3872   Input Parameters:
3873 + mat - the factored matrix
3874 - b   - the right-hand-side vector
3875 
3876   Output Parameter:
3877 . x - the result vector
3878 
3879   Level: developer
3880 
3881   Notes:
3882   `MatSolve()` should be used for most applications, as it performs
3883   a forward solve followed by a backward solve.
3884 
3885   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3886   call `MatBackwardSolve`(A,x,x).
3887 
3888   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3889   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3890   `MatForwardSolve()` solves U^T*D y = b, and
3891   `MatBackwardSolve()` solves U x = y.
3892   Thus they do not provide a symmetric preconditioner.
3893 
3894 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3895 @*/
3896 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3897 {
3898   PetscFunctionBegin;
3899   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3900   PetscValidType(mat, 1);
3901   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3902   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3903   PetscCheckSameComm(mat, 1, b, 2);
3904   PetscCheckSameComm(mat, 1, x, 3);
3905   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3906   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);
3907   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);
3908   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);
3909   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3910   MatCheckPreallocated(mat, 1);
3911 
3912   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3913   PetscUseTypeMethod(mat, backwardsolve, b, x);
3914   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3915   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3916   PetscFunctionReturn(PETSC_SUCCESS);
3917 }
3918 
3919 /*@
3920   MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3921 
3922   Neighbor-wise Collective
3923 
3924   Input Parameters:
3925 + mat - the factored matrix
3926 . b   - the right-hand-side vector
3927 - y   - the vector to be added to
3928 
3929   Output Parameter:
3930 . x - the result vector
3931 
3932   Level: developer
3933 
3934   Note:
3935   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3936   call `MatSolveAdd`(A,x,y,x).
3937 
3938 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3939 @*/
3940 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3941 {
3942   PetscScalar one = 1.0;
3943   Vec         tmp;
3944 
3945   PetscFunctionBegin;
3946   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3947   PetscValidType(mat, 1);
3948   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3949   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3950   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3951   PetscCheckSameComm(mat, 1, b, 2);
3952   PetscCheckSameComm(mat, 1, y, 3);
3953   PetscCheckSameComm(mat, 1, x, 4);
3954   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3955   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);
3956   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);
3957   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);
3958   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);
3959   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);
3960   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3961   MatCheckPreallocated(mat, 1);
3962 
3963   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3964   if (mat->factorerrortype) {
3965     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3966     PetscCall(VecSetInf(x));
3967   } else if (mat->ops->solveadd) {
3968     PetscUseTypeMethod(mat, solveadd, b, y, x);
3969   } else {
3970     /* do the solve then the add manually */
3971     if (x != y) {
3972       PetscCall(MatSolve(mat, b, x));
3973       PetscCall(VecAXPY(x, one, y));
3974     } else {
3975       PetscCall(VecDuplicate(x, &tmp));
3976       PetscCall(VecCopy(x, tmp));
3977       PetscCall(MatSolve(mat, b, x));
3978       PetscCall(VecAXPY(x, one, tmp));
3979       PetscCall(VecDestroy(&tmp));
3980     }
3981   }
3982   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3983   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3984   PetscFunctionReturn(PETSC_SUCCESS);
3985 }
3986 
3987 /*@
3988   MatSolveTranspose - Solves A' x = b, given a factored matrix.
3989 
3990   Neighbor-wise Collective
3991 
3992   Input Parameters:
3993 + mat - the factored matrix
3994 - b   - the right-hand-side vector
3995 
3996   Output Parameter:
3997 . x - the result vector
3998 
3999   Level: developer
4000 
4001   Notes:
4002   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4003   call `MatSolveTranspose`(A,x,x).
4004 
4005   Most users should employ the `KSP` interface for linear solvers
4006   instead of working directly with matrix algebra routines such as this.
4007   See, e.g., `KSPCreate()`.
4008 
4009 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4010 @*/
4011 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4012 {
4013   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4014 
4015   PetscFunctionBegin;
4016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4017   PetscValidType(mat, 1);
4018   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4019   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4020   PetscCheckSameComm(mat, 1, b, 2);
4021   PetscCheckSameComm(mat, 1, x, 3);
4022   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4023   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);
4024   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);
4025   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4026   MatCheckPreallocated(mat, 1);
4027   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4028   if (mat->factorerrortype) {
4029     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4030     PetscCall(VecSetInf(x));
4031   } else {
4032     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4033     PetscCall((*f)(mat, b, x));
4034   }
4035   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4036   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4037   PetscFunctionReturn(PETSC_SUCCESS);
4038 }
4039 
4040 /*@
4041   MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4042   factored matrix.
4043 
4044   Neighbor-wise Collective
4045 
4046   Input Parameters:
4047 + mat - the factored matrix
4048 . b   - the right-hand-side vector
4049 - y   - the vector to be added to
4050 
4051   Output Parameter:
4052 . x - the result vector
4053 
4054   Level: developer
4055 
4056   Note:
4057   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4058   call `MatSolveTransposeAdd`(A,x,y,x).
4059 
4060 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4061 @*/
4062 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4063 {
4064   PetscScalar one = 1.0;
4065   Vec         tmp;
4066   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4067 
4068   PetscFunctionBegin;
4069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4070   PetscValidType(mat, 1);
4071   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4072   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4073   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4074   PetscCheckSameComm(mat, 1, b, 2);
4075   PetscCheckSameComm(mat, 1, y, 3);
4076   PetscCheckSameComm(mat, 1, x, 4);
4077   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4078   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);
4079   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);
4080   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);
4081   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);
4082   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4083   MatCheckPreallocated(mat, 1);
4084 
4085   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4086   if (mat->factorerrortype) {
4087     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4088     PetscCall(VecSetInf(x));
4089   } else if (f) {
4090     PetscCall((*f)(mat, b, y, x));
4091   } else {
4092     /* do the solve then the add manually */
4093     if (x != y) {
4094       PetscCall(MatSolveTranspose(mat, b, x));
4095       PetscCall(VecAXPY(x, one, y));
4096     } else {
4097       PetscCall(VecDuplicate(x, &tmp));
4098       PetscCall(VecCopy(x, tmp));
4099       PetscCall(MatSolveTranspose(mat, b, x));
4100       PetscCall(VecAXPY(x, one, tmp));
4101       PetscCall(VecDestroy(&tmp));
4102     }
4103   }
4104   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4105   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4106   PetscFunctionReturn(PETSC_SUCCESS);
4107 }
4108 
4109 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4110 /*@
4111   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4112 
4113   Neighbor-wise Collective
4114 
4115   Input Parameters:
4116 + mat   - the matrix
4117 . b     - the right hand side
4118 . omega - the relaxation factor
4119 . flag  - flag indicating the type of SOR (see below)
4120 . shift - diagonal shift
4121 . its   - the number of iterations
4122 - lits  - the number of local iterations
4123 
4124   Output Parameter:
4125 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4126 
4127   SOR Flags:
4128 +     `SOR_FORWARD_SWEEP` - forward SOR
4129 .     `SOR_BACKWARD_SWEEP` - backward SOR
4130 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4131 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4132 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4133 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4134 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4135 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4136   upper/lower triangular part of matrix to
4137   vector (with omega)
4138 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4139 
4140   Level: developer
4141 
4142   Notes:
4143   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4144   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4145   on each processor.
4146 
4147   Application programmers will not generally use `MatSOR()` directly,
4148   but instead will employ the `KSP`/`PC` interface.
4149 
4150   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4151 
4152   Most users should employ the `KSP` interface for linear solvers
4153   instead of working directly with matrix algebra routines such as this.
4154   See, e.g., `KSPCreate()`.
4155 
4156   Vectors `x` and `b` CANNOT be the same
4157 
4158   The flags are implemented as bitwise inclusive or operations.
4159   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4160   to specify a zero initial guess for SSOR.
4161 
4162   Developer Notes:
4163   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4164 
4165 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4166 @*/
4167 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4168 {
4169   PetscFunctionBegin;
4170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4171   PetscValidType(mat, 1);
4172   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4173   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4174   PetscCheckSameComm(mat, 1, b, 2);
4175   PetscCheckSameComm(mat, 1, x, 8);
4176   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4177   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4178   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);
4179   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);
4180   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);
4181   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4182   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4183   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4184 
4185   MatCheckPreallocated(mat, 1);
4186   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4187   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4188   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4189   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4190   PetscFunctionReturn(PETSC_SUCCESS);
4191 }
4192 
4193 /*
4194       Default matrix copy routine.
4195 */
4196 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4197 {
4198   PetscInt           i, rstart = 0, rend = 0, nz;
4199   const PetscInt    *cwork;
4200   const PetscScalar *vwork;
4201 
4202   PetscFunctionBegin;
4203   if (B->assembled) PetscCall(MatZeroEntries(B));
4204   if (str == SAME_NONZERO_PATTERN) {
4205     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4206     for (i = rstart; i < rend; i++) {
4207       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4208       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4209       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4210     }
4211   } else {
4212     PetscCall(MatAYPX(B, 0.0, A, str));
4213   }
4214   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4215   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4216   PetscFunctionReturn(PETSC_SUCCESS);
4217 }
4218 
4219 /*@
4220   MatCopy - Copies a matrix to another matrix.
4221 
4222   Collective
4223 
4224   Input Parameters:
4225 + A   - the matrix
4226 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4227 
4228   Output Parameter:
4229 . B - where the copy is put
4230 
4231   Level: intermediate
4232 
4233   Notes:
4234   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4235 
4236   `MatCopy()` copies the matrix entries of a matrix to another existing
4237   matrix (after first zeroing the second matrix).  A related routine is
4238   `MatConvert()`, which first creates a new matrix and then copies the data.
4239 
4240 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4241 @*/
4242 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4243 {
4244   PetscInt i;
4245 
4246   PetscFunctionBegin;
4247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4248   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4249   PetscValidType(A, 1);
4250   PetscValidType(B, 2);
4251   PetscCheckSameComm(A, 1, B, 2);
4252   MatCheckPreallocated(B, 2);
4253   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4254   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4255   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,
4256              A->cmap->N, B->cmap->N);
4257   MatCheckPreallocated(A, 1);
4258   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4259 
4260   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4261   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4262   else PetscCall(MatCopy_Basic(A, B, str));
4263 
4264   B->stencil.dim = A->stencil.dim;
4265   B->stencil.noc = A->stencil.noc;
4266   for (i = 0; i <= A->stencil.dim; i++) {
4267     B->stencil.dims[i]   = A->stencil.dims[i];
4268     B->stencil.starts[i] = A->stencil.starts[i];
4269   }
4270 
4271   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4272   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4273   PetscFunctionReturn(PETSC_SUCCESS);
4274 }
4275 
4276 /*@C
4277   MatConvert - Converts a matrix to another matrix, either of the same
4278   or different type.
4279 
4280   Collective
4281 
4282   Input Parameters:
4283 + mat     - the matrix
4284 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4285    same type as the original matrix.
4286 - reuse   - denotes if the destination matrix is to be created or reused.
4287    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
4288    `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).
4289 
4290   Output Parameter:
4291 . M - pointer to place new matrix
4292 
4293   Level: intermediate
4294 
4295   Notes:
4296   `MatConvert()` first creates a new matrix and then copies the data from
4297   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4298   entries of one matrix to another already existing matrix context.
4299 
4300   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4301   the MPI communicator of the generated matrix is always the same as the communicator
4302   of the input matrix.
4303 
4304 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4305 @*/
4306 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4307 {
4308   PetscBool  sametype, issame, flg;
4309   PetscBool3 issymmetric, ishermitian;
4310   char       convname[256], mtype[256];
4311   Mat        B;
4312 
4313   PetscFunctionBegin;
4314   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4315   PetscValidType(mat, 1);
4316   PetscValidPointer(M, 4);
4317   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4318   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4319   MatCheckPreallocated(mat, 1);
4320 
4321   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4322   if (flg) newtype = mtype;
4323 
4324   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4325   PetscCall(PetscStrcmp(newtype, "same", &issame));
4326   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4327   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4328 
4329   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4330     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4331     PetscFunctionReturn(PETSC_SUCCESS);
4332   }
4333 
4334   /* Cache Mat options because some converters use MatHeaderReplace  */
4335   issymmetric = mat->symmetric;
4336   ishermitian = mat->hermitian;
4337 
4338   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4339     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4340     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4341   } else {
4342     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4343     const char *prefix[3]                                 = {"seq", "mpi", ""};
4344     PetscInt    i;
4345     /*
4346        Order of precedence:
4347        0) See if newtype is a superclass of the current matrix.
4348        1) See if a specialized converter is known to the current matrix.
4349        2) See if a specialized converter is known to the desired matrix class.
4350        3) See if a good general converter is registered for the desired class
4351           (as of 6/27/03 only MATMPIADJ falls into this category).
4352        4) See if a good general converter is known for the current matrix.
4353        5) Use a really basic converter.
4354     */
4355 
4356     /* 0) See if newtype is a superclass of the current matrix.
4357           i.e mat is mpiaij and newtype is aij */
4358     for (i = 0; i < 2; i++) {
4359       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4361       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4362       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4363       if (flg) {
4364         if (reuse == MAT_INPLACE_MATRIX) {
4365           PetscCall(PetscInfo(mat, "Early return\n"));
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4368           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4369           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4372           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4373           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4374           PetscFunctionReturn(PETSC_SUCCESS);
4375         }
4376       }
4377     }
4378     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4379     for (i = 0; i < 3; i++) {
4380       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4381       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4382       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4383       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4384       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4385       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4386       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4387       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4388       if (conv) goto foundconv;
4389     }
4390 
4391     /* 2)  See if a specialized converter is known to the desired matrix class. */
4392     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4393     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4394     PetscCall(MatSetType(B, newtype));
4395     for (i = 0; i < 3; i++) {
4396       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4397       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4398       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4399       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4400       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4401       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4402       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4403       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4404       if (conv) {
4405         PetscCall(MatDestroy(&B));
4406         goto foundconv;
4407       }
4408     }
4409 
4410     /* 3) See if a good general converter is registered for the desired class */
4411     conv = B->ops->convertfrom;
4412     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4413     PetscCall(MatDestroy(&B));
4414     if (conv) goto foundconv;
4415 
4416     /* 4) See if a good general converter is known for the current matrix */
4417     if (mat->ops->convert) conv = mat->ops->convert;
4418     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4419     if (conv) goto foundconv;
4420 
4421     /* 5) Use a really basic converter. */
4422     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4423     conv = MatConvert_Basic;
4424 
4425   foundconv:
4426     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4427     PetscCall((*conv)(mat, newtype, reuse, M));
4428     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4429       /* the block sizes must be same if the mappings are copied over */
4430       (*M)->rmap->bs = mat->rmap->bs;
4431       (*M)->cmap->bs = mat->cmap->bs;
4432       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4433       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4434       (*M)->rmap->mapping = mat->rmap->mapping;
4435       (*M)->cmap->mapping = mat->cmap->mapping;
4436     }
4437     (*M)->stencil.dim = mat->stencil.dim;
4438     (*M)->stencil.noc = mat->stencil.noc;
4439     for (i = 0; i <= mat->stencil.dim; i++) {
4440       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4441       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4442     }
4443     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4444   }
4445   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4446 
4447   /* Copy Mat options */
4448   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4449   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4450   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4451   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4452   PetscFunctionReturn(PETSC_SUCCESS);
4453 }
4454 
4455 /*@C
4456   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4457 
4458   Not Collective
4459 
4460   Input Parameter:
4461 . mat - the matrix, must be a factored matrix
4462 
4463   Output Parameter:
4464 . type - the string name of the package (do not free this string)
4465 
4466   Level: intermediate
4467 
4468   Fortran Notes:
4469   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4470 
4471 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4472 @*/
4473 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4474 {
4475   PetscErrorCode (*conv)(Mat, MatSolverType *);
4476 
4477   PetscFunctionBegin;
4478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4479   PetscValidType(mat, 1);
4480   PetscValidPointer(type, 2);
4481   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4482   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4483   if (conv) PetscCall((*conv)(mat, type));
4484   else *type = MATSOLVERPETSC;
4485   PetscFunctionReturn(PETSC_SUCCESS);
4486 }
4487 
4488 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4489 struct _MatSolverTypeForSpecifcType {
4490   MatType mtype;
4491   /* no entry for MAT_FACTOR_NONE */
4492   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4493   MatSolverTypeForSpecifcType next;
4494 };
4495 
4496 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4497 struct _MatSolverTypeHolder {
4498   char                       *name;
4499   MatSolverTypeForSpecifcType handlers;
4500   MatSolverTypeHolder         next;
4501 };
4502 
4503 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4504 
4505 /*@C
4506   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4507 
4508   Input Parameters:
4509 + package      - name of the package, for example petsc or superlu
4510 . mtype        - the matrix type that works with this package
4511 . ftype        - the type of factorization supported by the package
4512 - createfactor - routine that will create the factored matrix ready to be used
4513 
4514   Level: developer
4515 
4516 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4517 @*/
4518 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4519 {
4520   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4521   PetscBool                   flg;
4522   MatSolverTypeForSpecifcType inext, iprev = NULL;
4523 
4524   PetscFunctionBegin;
4525   PetscCall(MatInitializePackage());
4526   if (!next) {
4527     PetscCall(PetscNew(&MatSolverTypeHolders));
4528     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4529     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4530     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4531     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4532     PetscFunctionReturn(PETSC_SUCCESS);
4533   }
4534   while (next) {
4535     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4536     if (flg) {
4537       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4538       inext = next->handlers;
4539       while (inext) {
4540         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4541         if (flg) {
4542           inext->createfactor[(int)ftype - 1] = createfactor;
4543           PetscFunctionReturn(PETSC_SUCCESS);
4544         }
4545         iprev = inext;
4546         inext = inext->next;
4547       }
4548       PetscCall(PetscNew(&iprev->next));
4549       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4550       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4551       PetscFunctionReturn(PETSC_SUCCESS);
4552     }
4553     prev = next;
4554     next = next->next;
4555   }
4556   PetscCall(PetscNew(&prev->next));
4557   PetscCall(PetscStrallocpy(package, &prev->next->name));
4558   PetscCall(PetscNew(&prev->next->handlers));
4559   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4560   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4561   PetscFunctionReturn(PETSC_SUCCESS);
4562 }
4563 
4564 /*@C
4565   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4566 
4567   Input Parameters:
4568 + type  - name of the package, for example petsc or superlu
4569 . ftype - the type of factorization supported by the type
4570 - mtype - the matrix type that works with this type
4571 
4572   Output Parameters:
4573 + foundtype    - `PETSC_TRUE` if the type was registered
4574 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4575 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4576 
4577   Level: developer
4578 
4579 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4580 @*/
4581 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4582 {
4583   MatSolverTypeHolder         next = MatSolverTypeHolders;
4584   PetscBool                   flg;
4585   MatSolverTypeForSpecifcType inext;
4586 
4587   PetscFunctionBegin;
4588   if (foundtype) *foundtype = PETSC_FALSE;
4589   if (foundmtype) *foundmtype = PETSC_FALSE;
4590   if (createfactor) *createfactor = NULL;
4591 
4592   if (type) {
4593     while (next) {
4594       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4595       if (flg) {
4596         if (foundtype) *foundtype = PETSC_TRUE;
4597         inext = next->handlers;
4598         while (inext) {
4599           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4600           if (flg) {
4601             if (foundmtype) *foundmtype = PETSC_TRUE;
4602             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4603             PetscFunctionReturn(PETSC_SUCCESS);
4604           }
4605           inext = inext->next;
4606         }
4607       }
4608       next = next->next;
4609     }
4610   } else {
4611     while (next) {
4612       inext = next->handlers;
4613       while (inext) {
4614         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4615         if (flg && inext->createfactor[(int)ftype - 1]) {
4616           if (foundtype) *foundtype = PETSC_TRUE;
4617           if (foundmtype) *foundmtype = PETSC_TRUE;
4618           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4619           PetscFunctionReturn(PETSC_SUCCESS);
4620         }
4621         inext = inext->next;
4622       }
4623       next = next->next;
4624     }
4625     /* try with base classes inext->mtype */
4626     next = MatSolverTypeHolders;
4627     while (next) {
4628       inext = next->handlers;
4629       while (inext) {
4630         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4631         if (flg && inext->createfactor[(int)ftype - 1]) {
4632           if (foundtype) *foundtype = PETSC_TRUE;
4633           if (foundmtype) *foundmtype = PETSC_TRUE;
4634           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4635           PetscFunctionReturn(PETSC_SUCCESS);
4636         }
4637         inext = inext->next;
4638       }
4639       next = next->next;
4640     }
4641   }
4642   PetscFunctionReturn(PETSC_SUCCESS);
4643 }
4644 
4645 PetscErrorCode MatSolverTypeDestroy(void)
4646 {
4647   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4648   MatSolverTypeForSpecifcType inext, iprev;
4649 
4650   PetscFunctionBegin;
4651   while (next) {
4652     PetscCall(PetscFree(next->name));
4653     inext = next->handlers;
4654     while (inext) {
4655       PetscCall(PetscFree(inext->mtype));
4656       iprev = inext;
4657       inext = inext->next;
4658       PetscCall(PetscFree(iprev));
4659     }
4660     prev = next;
4661     next = next->next;
4662     PetscCall(PetscFree(prev));
4663   }
4664   MatSolverTypeHolders = NULL;
4665   PetscFunctionReturn(PETSC_SUCCESS);
4666 }
4667 
4668 /*@C
4669   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4670 
4671   Logically Collective
4672 
4673   Input Parameter:
4674 . mat - the matrix
4675 
4676   Output Parameter:
4677 . flg - `PETSC_TRUE` if uses the ordering
4678 
4679   Level: developer
4680 
4681   Note:
4682   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4683   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4684 
4685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4686 @*/
4687 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4688 {
4689   PetscFunctionBegin;
4690   *flg = mat->canuseordering;
4691   PetscFunctionReturn(PETSC_SUCCESS);
4692 }
4693 
4694 /*@C
4695   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4696 
4697   Logically Collective
4698 
4699   Input Parameters:
4700 + mat   - the matrix obtained with `MatGetFactor()`
4701 - ftype - the factorization type to be used
4702 
4703   Output Parameter:
4704 . otype - the preferred ordering type
4705 
4706   Level: developer
4707 
4708 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4709 @*/
4710 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4711 {
4712   PetscFunctionBegin;
4713   *otype = mat->preferredordering[ftype];
4714   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4715   PetscFunctionReturn(PETSC_SUCCESS);
4716 }
4717 
4718 /*@C
4719   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4720 
4721   Collective
4722 
4723   Input Parameters:
4724 + mat   - the matrix
4725 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4726 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4727 
4728   Output Parameter:
4729 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4730 
4731   Options Database Key:
4732 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4733                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4734 
4735   Level: intermediate
4736 
4737   Notes:
4738   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4739   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4740 
4741   Users usually access the factorization solvers via `KSP`
4742 
4743   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4744   such as pastix, superlu, mumps etc.
4745 
4746   PETSc must have been ./configure to use the external solver, using the option --download-package
4747 
4748   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4749   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4750   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4751 
4752   Developer Notes:
4753   This should actually be called `MatCreateFactor()` since it creates a new factor object
4754 
4755 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4756           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4757 @*/
4758 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4759 {
4760   PetscBool foundtype, foundmtype;
4761   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4762 
4763   PetscFunctionBegin;
4764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4765   PetscValidType(mat, 1);
4766 
4767   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4768   MatCheckPreallocated(mat, 1);
4769 
4770   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4771   if (!foundtype) {
4772     if (type) {
4773       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],
4774               ((PetscObject)mat)->type_name, type);
4775     } else {
4776       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);
4777     }
4778   }
4779   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4780   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);
4781 
4782   PetscCall((*conv)(mat, ftype, f));
4783   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4784   PetscFunctionReturn(PETSC_SUCCESS);
4785 }
4786 
4787 /*@C
4788   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4789 
4790   Not Collective
4791 
4792   Input Parameters:
4793 + mat   - the matrix
4794 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4795 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4796 
4797   Output Parameter:
4798 . flg - PETSC_TRUE if the factorization is available
4799 
4800   Level: intermediate
4801 
4802   Notes:
4803   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4804   such as pastix, superlu, mumps etc.
4805 
4806   PETSc must have been ./configure to use the external solver, using the option --download-package
4807 
4808   Developer Notes:
4809   This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4810 
4811 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4812           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4813 @*/
4814 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4815 {
4816   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4817 
4818   PetscFunctionBegin;
4819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4820   PetscValidType(mat, 1);
4821   PetscValidBoolPointer(flg, 4);
4822 
4823   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4824   MatCheckPreallocated(mat, 1);
4825 
4826   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4827   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4828   PetscFunctionReturn(PETSC_SUCCESS);
4829 }
4830 
4831 /*@
4832   MatDuplicate - Duplicates a matrix including the non-zero structure.
4833 
4834   Collective
4835 
4836   Input Parameters:
4837 + mat - the matrix
4838 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4839         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4840 
4841   Output Parameter:
4842 . M - pointer to place new matrix
4843 
4844   Level: intermediate
4845 
4846   Notes:
4847   You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4848 
4849   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.
4850 
4851   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4852   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4853   User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4854 
4855 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4856 @*/
4857 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4858 {
4859   Mat         B;
4860   VecType     vtype;
4861   PetscInt    i;
4862   PetscObject dm, container_h, container_d;
4863   void (*viewf)(void);
4864 
4865   PetscFunctionBegin;
4866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4867   PetscValidType(mat, 1);
4868   PetscValidPointer(M, 3);
4869   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4870   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4871   MatCheckPreallocated(mat, 1);
4872 
4873   *M = NULL;
4874   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4875   PetscUseTypeMethod(mat, duplicate, op, M);
4876   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4877   B = *M;
4878 
4879   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4880   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4881   PetscCall(MatGetVecType(mat, &vtype));
4882   PetscCall(MatSetVecType(B, vtype));
4883 
4884   B->stencil.dim = mat->stencil.dim;
4885   B->stencil.noc = mat->stencil.noc;
4886   for (i = 0; i <= mat->stencil.dim; i++) {
4887     B->stencil.dims[i]   = mat->stencil.dims[i];
4888     B->stencil.starts[i] = mat->stencil.starts[i];
4889   }
4890 
4891   B->nooffproczerorows = mat->nooffproczerorows;
4892   B->nooffprocentries  = mat->nooffprocentries;
4893 
4894   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4895   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4896   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4897   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4898   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4899   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4900   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4901   PetscFunctionReturn(PETSC_SUCCESS);
4902 }
4903 
4904 /*@
4905   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4906 
4907   Logically Collective
4908 
4909   Input Parameter:
4910 . mat - the matrix
4911 
4912   Output Parameter:
4913 . v - the diagonal of the matrix
4914 
4915   Level: intermediate
4916 
4917   Note:
4918   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4919   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4920   is larger than `ndiag`, the values of the remaining entries are unspecified.
4921 
4922   Currently only correct in parallel for square matrices.
4923 
4924 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4925 @*/
4926 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4927 {
4928   PetscFunctionBegin;
4929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4930   PetscValidType(mat, 1);
4931   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4932   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4933   MatCheckPreallocated(mat, 1);
4934   if (PetscDefined(USE_DEBUG)) {
4935     PetscInt nv, row, col, ndiag;
4936 
4937     PetscCall(VecGetLocalSize(v, &nv));
4938     PetscCall(MatGetLocalSize(mat, &row, &col));
4939     ndiag = PetscMin(row, col);
4940     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);
4941   }
4942 
4943   PetscUseTypeMethod(mat, getdiagonal, v);
4944   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4945   PetscFunctionReturn(PETSC_SUCCESS);
4946 }
4947 
4948 /*@C
4949   MatGetRowMin - Gets the minimum value (of the real part) of each
4950   row of the matrix
4951 
4952   Logically Collective
4953 
4954   Input Parameter:
4955 . mat - the matrix
4956 
4957   Output Parameters:
4958 + v   - the vector for storing the maximums
4959 - idx - the indices of the column found for each row (optional)
4960 
4961   Level: intermediate
4962 
4963   Note:
4964   The result of this call are the same as if one converted the matrix to dense format
4965   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4966 
4967   This code is only implemented for a couple of matrix formats.
4968 
4969 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4970           `MatGetRowMax()`
4971 @*/
4972 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4973 {
4974   PetscFunctionBegin;
4975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4976   PetscValidType(mat, 1);
4977   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4978   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4979 
4980   if (!mat->cmap->N) {
4981     PetscCall(VecSet(v, PETSC_MAX_REAL));
4982     if (idx) {
4983       PetscInt i, m = mat->rmap->n;
4984       for (i = 0; i < m; i++) idx[i] = -1;
4985     }
4986   } else {
4987     MatCheckPreallocated(mat, 1);
4988   }
4989   PetscUseTypeMethod(mat, getrowmin, v, idx);
4990   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4991   PetscFunctionReturn(PETSC_SUCCESS);
4992 }
4993 
4994 /*@C
4995   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4996   row of the matrix
4997 
4998   Logically Collective
4999 
5000   Input Parameter:
5001 . mat - the matrix
5002 
5003   Output Parameters:
5004 + v   - the vector for storing the minimums
5005 - idx - the indices of the column found for each row (or `NULL` if not needed)
5006 
5007   Level: intermediate
5008 
5009   Notes:
5010   if a row is completely empty or has only 0.0 values then the idx[] value for that
5011   row is 0 (the first column).
5012 
5013   This code is only implemented for a couple of matrix formats.
5014 
5015 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5016 @*/
5017 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5018 {
5019   PetscFunctionBegin;
5020   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5021   PetscValidType(mat, 1);
5022   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5023   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5024   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5025 
5026   if (!mat->cmap->N) {
5027     PetscCall(VecSet(v, 0.0));
5028     if (idx) {
5029       PetscInt i, m = mat->rmap->n;
5030       for (i = 0; i < m; i++) idx[i] = -1;
5031     }
5032   } else {
5033     MatCheckPreallocated(mat, 1);
5034     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5035     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5036   }
5037   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5038   PetscFunctionReturn(PETSC_SUCCESS);
5039 }
5040 
5041 /*@C
5042   MatGetRowMax - Gets the maximum value (of the real part) of each
5043   row of the matrix
5044 
5045   Logically Collective
5046 
5047   Input Parameter:
5048 . mat - the matrix
5049 
5050   Output Parameters:
5051 + v   - the vector for storing the maximums
5052 - idx - the indices of the column found for each row (optional)
5053 
5054   Level: intermediate
5055 
5056   Notes:
5057   The result of this call are the same as if one converted the matrix to dense format
5058   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5059 
5060   This code is only implemented for a couple of matrix formats.
5061 
5062 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5063 @*/
5064 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5065 {
5066   PetscFunctionBegin;
5067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5068   PetscValidType(mat, 1);
5069   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5071 
5072   if (!mat->cmap->N) {
5073     PetscCall(VecSet(v, PETSC_MIN_REAL));
5074     if (idx) {
5075       PetscInt i, m = mat->rmap->n;
5076       for (i = 0; i < m; i++) idx[i] = -1;
5077     }
5078   } else {
5079     MatCheckPreallocated(mat, 1);
5080     PetscUseTypeMethod(mat, getrowmax, v, idx);
5081   }
5082   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5083   PetscFunctionReturn(PETSC_SUCCESS);
5084 }
5085 
5086 /*@C
5087   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5088   row of the matrix
5089 
5090   Logically Collective
5091 
5092   Input Parameter:
5093 . mat - the matrix
5094 
5095   Output Parameters:
5096 + v   - the vector for storing the maximums
5097 - idx - the indices of the column found for each row (or `NULL` if not needed)
5098 
5099   Level: intermediate
5100 
5101   Notes:
5102   if a row is completely empty or has only 0.0 values then the idx[] value for that
5103   row is 0 (the first column).
5104 
5105   This code is only implemented for a couple of matrix formats.
5106 
5107 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5108 @*/
5109 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5110 {
5111   PetscFunctionBegin;
5112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5113   PetscValidType(mat, 1);
5114   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5115   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5116 
5117   if (!mat->cmap->N) {
5118     PetscCall(VecSet(v, 0.0));
5119     if (idx) {
5120       PetscInt i, m = mat->rmap->n;
5121       for (i = 0; i < m; i++) idx[i] = -1;
5122     }
5123   } else {
5124     MatCheckPreallocated(mat, 1);
5125     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5126     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5127   }
5128   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5129   PetscFunctionReturn(PETSC_SUCCESS);
5130 }
5131 
5132 /*@
5133   MatGetRowSum - Gets the sum of each row of the matrix
5134 
5135   Logically or Neighborhood Collective
5136 
5137   Input Parameter:
5138 . mat - the matrix
5139 
5140   Output Parameter:
5141 . v - the vector for storing the sum of rows
5142 
5143   Level: intermediate
5144 
5145   Notes:
5146   This code is slow since it is not currently specialized for different formats
5147 
5148 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5149 @*/
5150 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5151 {
5152   Vec ones;
5153 
5154   PetscFunctionBegin;
5155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5156   PetscValidType(mat, 1);
5157   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5158   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5159   MatCheckPreallocated(mat, 1);
5160   PetscCall(MatCreateVecs(mat, &ones, NULL));
5161   PetscCall(VecSet(ones, 1.));
5162   PetscCall(MatMult(mat, ones, v));
5163   PetscCall(VecDestroy(&ones));
5164   PetscFunctionReturn(PETSC_SUCCESS);
5165 }
5166 
5167 /*@
5168   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5169   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5170 
5171   Collective
5172 
5173   Input Parameter:
5174 . mat - the matrix to provide the transpose
5175 
5176   Output Parameter:
5177 . 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
5178 
5179   Level: advanced
5180 
5181   Note:
5182   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
5183   routine allows bypassing that call.
5184 
5185 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5186 @*/
5187 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5188 {
5189   PetscContainer  rB = NULL;
5190   MatParentState *rb = NULL;
5191 
5192   PetscFunctionBegin;
5193   PetscCall(PetscNew(&rb));
5194   rb->id    = ((PetscObject)mat)->id;
5195   rb->state = 0;
5196   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5197   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5198   PetscCall(PetscContainerSetPointer(rB, rb));
5199   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5200   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5201   PetscCall(PetscObjectDereference((PetscObject)rB));
5202   PetscFunctionReturn(PETSC_SUCCESS);
5203 }
5204 
5205 /*@
5206   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5207 
5208   Collective
5209 
5210   Input Parameters:
5211 + mat   - the matrix to transpose
5212 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5213 
5214   Output Parameter:
5215 . B - the transpose
5216 
5217   Level: intermediate
5218 
5219   Notes:
5220   If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5221 
5222   `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
5223   transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5224 
5225   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.
5226 
5227   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5228 
5229   If mat is unchanged from the last call this function returns immediately without recomputing the result
5230 
5231   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5232 
5233 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5234           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5235 @*/
5236 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5237 {
5238   PetscContainer  rB = NULL;
5239   MatParentState *rb = NULL;
5240 
5241   PetscFunctionBegin;
5242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5243   PetscValidType(mat, 1);
5244   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5245   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5246   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5247   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5248   MatCheckPreallocated(mat, 1);
5249   if (reuse == MAT_REUSE_MATRIX) {
5250     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5251     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5252     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5253     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5254     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5255   }
5256 
5257   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5258   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5259     PetscUseTypeMethod(mat, transpose, reuse, B);
5260     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5261   }
5262   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5263 
5264   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5265   if (reuse != MAT_INPLACE_MATRIX) {
5266     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5267     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5268     rb->state        = ((PetscObject)mat)->state;
5269     rb->nonzerostate = mat->nonzerostate;
5270   }
5271   PetscFunctionReturn(PETSC_SUCCESS);
5272 }
5273 
5274 /*@
5275   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5276 
5277   Collective
5278 
5279   Input Parameter:
5280 . A - the matrix to transpose
5281 
5282   Output Parameter:
5283 . 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
5284       numerical portion.
5285 
5286   Level: intermediate
5287 
5288   Note:
5289   This is not supported for many matrix types, use `MatTranspose()` in those cases
5290 
5291 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5292 @*/
5293 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5294 {
5295   PetscFunctionBegin;
5296   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5297   PetscValidType(A, 1);
5298   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5299   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5300   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5301   PetscUseTypeMethod(A, transposesymbolic, B);
5302   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5303 
5304   PetscCall(MatTransposeSetPrecursor(A, *B));
5305   PetscFunctionReturn(PETSC_SUCCESS);
5306 }
5307 
5308 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5309 {
5310   PetscContainer  rB;
5311   MatParentState *rb;
5312 
5313   PetscFunctionBegin;
5314   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5315   PetscValidType(A, 1);
5316   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5317   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5318   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5319   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5320   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5321   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5322   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5323   PetscFunctionReturn(PETSC_SUCCESS);
5324 }
5325 
5326 /*@
5327   MatIsTranspose - Test whether a matrix is another one's transpose,
5328   or its own, in which case it tests symmetry.
5329 
5330   Collective
5331 
5332   Input Parameters:
5333 + A   - the matrix to test
5334 . B   - the matrix to test against, this can equal the first parameter
5335 - tol - tolerance, differences between entries smaller than this are counted as zero
5336 
5337   Output Parameter:
5338 . flg - the result
5339 
5340   Level: intermediate
5341 
5342   Notes:
5343   Only available for `MATAIJ` matrices.
5344 
5345   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5346   test involves parallel copies of the block-offdiagonal parts of the matrix.
5347 
5348 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5349 @*/
5350 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5351 {
5352   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5353 
5354   PetscFunctionBegin;
5355   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5356   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5357   PetscValidBoolPointer(flg, 4);
5358   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5359   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5360   *flg = PETSC_FALSE;
5361   if (f && g) {
5362     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5363     PetscCall((*f)(A, B, tol, flg));
5364   } else {
5365     MatType mattype;
5366 
5367     PetscCall(MatGetType(f ? B : A, &mattype));
5368     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5369   }
5370   PetscFunctionReturn(PETSC_SUCCESS);
5371 }
5372 
5373 /*@
5374   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5375 
5376   Collective
5377 
5378   Input Parameters:
5379 + mat   - the matrix to transpose and complex conjugate
5380 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5381 
5382   Output Parameter:
5383 . B - the Hermitian transpose
5384 
5385   Level: intermediate
5386 
5387 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5388 @*/
5389 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5390 {
5391   PetscFunctionBegin;
5392   PetscCall(MatTranspose(mat, reuse, B));
5393 #if defined(PETSC_USE_COMPLEX)
5394   PetscCall(MatConjugate(*B));
5395 #endif
5396   PetscFunctionReturn(PETSC_SUCCESS);
5397 }
5398 
5399 /*@
5400   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5401 
5402   Collective
5403 
5404   Input Parameters:
5405 + A   - the matrix to test
5406 . B   - the matrix to test against, this can equal the first parameter
5407 - tol - tolerance, differences between entries smaller than this are counted as zero
5408 
5409   Output Parameter:
5410 . flg - the result
5411 
5412   Level: intermediate
5413 
5414   Notes:
5415   Only available for `MATAIJ` matrices.
5416 
5417   The sequential algorithm
5418   has a running time of the order of the number of nonzeros; the parallel
5419   test involves parallel copies of the block-offdiagonal parts of the matrix.
5420 
5421 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5422 @*/
5423 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5424 {
5425   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5426 
5427   PetscFunctionBegin;
5428   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5429   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5430   PetscValidBoolPointer(flg, 4);
5431   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5432   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5433   if (f && g) {
5434     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5435     PetscCall((*f)(A, B, tol, flg));
5436   }
5437   PetscFunctionReturn(PETSC_SUCCESS);
5438 }
5439 
5440 /*@
5441   MatPermute - Creates a new matrix with rows and columns permuted from the
5442   original.
5443 
5444   Collective
5445 
5446   Input Parameters:
5447 + mat - the matrix to permute
5448 . row - row permutation, each processor supplies only the permutation for its rows
5449 - col - column permutation, each processor supplies only the permutation for its columns
5450 
5451   Output Parameter:
5452 . B - the permuted matrix
5453 
5454   Level: advanced
5455 
5456   Note:
5457   The index sets map from row/col of permuted matrix to row/col of original matrix.
5458   The index sets should be on the same communicator as mat and have the same local sizes.
5459 
5460   Developer Notes:
5461   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5462   exploit the fact that row and col are permutations, consider implementing the
5463   more general `MatCreateSubMatrix()` instead.
5464 
5465 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5466 @*/
5467 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5468 {
5469   PetscFunctionBegin;
5470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5471   PetscValidType(mat, 1);
5472   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5473   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5474   PetscValidPointer(B, 4);
5475   PetscCheckSameComm(mat, 1, row, 2);
5476   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5477   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5478   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5479   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5480   MatCheckPreallocated(mat, 1);
5481 
5482   if (mat->ops->permute) {
5483     PetscUseTypeMethod(mat, permute, row, col, B);
5484     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5485   } else {
5486     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5487   }
5488   PetscFunctionReturn(PETSC_SUCCESS);
5489 }
5490 
5491 /*@
5492   MatEqual - Compares two matrices.
5493 
5494   Collective
5495 
5496   Input Parameters:
5497 + A - the first matrix
5498 - B - the second matrix
5499 
5500   Output Parameter:
5501 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5502 
5503   Level: intermediate
5504 
5505 .seealso: [](ch_matrices), `Mat`
5506 @*/
5507 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5508 {
5509   PetscFunctionBegin;
5510   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5511   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5512   PetscValidType(A, 1);
5513   PetscValidType(B, 2);
5514   PetscValidBoolPointer(flg, 3);
5515   PetscCheckSameComm(A, 1, B, 2);
5516   MatCheckPreallocated(A, 1);
5517   MatCheckPreallocated(B, 2);
5518   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5519   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5520   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,
5521              B->cmap->N);
5522   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5523     PetscUseTypeMethod(A, equal, B, flg);
5524   } else {
5525     PetscCall(MatMultEqual(A, B, 10, flg));
5526   }
5527   PetscFunctionReturn(PETSC_SUCCESS);
5528 }
5529 
5530 /*@
5531   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5532   matrices that are stored as vectors.  Either of the two scaling
5533   matrices can be `NULL`.
5534 
5535   Collective
5536 
5537   Input Parameters:
5538 + mat - the matrix to be scaled
5539 . l   - the left scaling vector (or `NULL`)
5540 - r   - the right scaling vector (or `NULL`)
5541 
5542   Level: intermediate
5543 
5544   Note:
5545   `MatDiagonalScale()` computes A = LAR, where
5546   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5547   The L scales the rows of the matrix, the R scales the columns of the matrix.
5548 
5549 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5550 @*/
5551 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5552 {
5553   PetscFunctionBegin;
5554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5555   PetscValidType(mat, 1);
5556   if (l) {
5557     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5558     PetscCheckSameComm(mat, 1, l, 2);
5559   }
5560   if (r) {
5561     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5562     PetscCheckSameComm(mat, 1, r, 3);
5563   }
5564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5566   MatCheckPreallocated(mat, 1);
5567   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5568 
5569   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5570   PetscUseTypeMethod(mat, diagonalscale, l, r);
5571   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5572   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5573   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5574   PetscFunctionReturn(PETSC_SUCCESS);
5575 }
5576 
5577 /*@
5578   MatScale - Scales all elements of a matrix by a given number.
5579 
5580   Logically Collective
5581 
5582   Input Parameters:
5583 + mat - the matrix to be scaled
5584 - a   - the scaling value
5585 
5586   Level: intermediate
5587 
5588 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5589 @*/
5590 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5591 {
5592   PetscFunctionBegin;
5593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5594   PetscValidType(mat, 1);
5595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5597   PetscValidLogicalCollectiveScalar(mat, a, 2);
5598   MatCheckPreallocated(mat, 1);
5599 
5600   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5601   if (a != (PetscScalar)1.0) {
5602     PetscUseTypeMethod(mat, scale, a);
5603     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5604   }
5605   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5606   PetscFunctionReturn(PETSC_SUCCESS);
5607 }
5608 
5609 /*@
5610   MatNorm - Calculates various norms of a matrix.
5611 
5612   Collective
5613 
5614   Input Parameters:
5615 + mat  - the matrix
5616 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5617 
5618   Output Parameter:
5619 . nrm - the resulting norm
5620 
5621   Level: intermediate
5622 
5623 .seealso: [](ch_matrices), `Mat`
5624 @*/
5625 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5626 {
5627   PetscFunctionBegin;
5628   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5629   PetscValidType(mat, 1);
5630   PetscValidRealPointer(nrm, 3);
5631 
5632   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5633   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5634   MatCheckPreallocated(mat, 1);
5635 
5636   PetscUseTypeMethod(mat, norm, type, nrm);
5637   PetscFunctionReturn(PETSC_SUCCESS);
5638 }
5639 
5640 /*
5641      This variable is used to prevent counting of MatAssemblyBegin() that
5642    are called from within a MatAssemblyEnd().
5643 */
5644 static PetscInt MatAssemblyEnd_InUse = 0;
5645 /*@
5646   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5647   be called after completing all calls to `MatSetValues()`.
5648 
5649   Collective
5650 
5651   Input Parameters:
5652 + mat  - the matrix
5653 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5654 
5655   Level: beginner
5656 
5657   Notes:
5658   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5659   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5660 
5661   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5662   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5663   using the matrix.
5664 
5665   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5666   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
5667   a global collective operation requiring all processes that share the matrix.
5668 
5669   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5670   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5671   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5672 
5673 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5674 @*/
5675 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5676 {
5677   PetscFunctionBegin;
5678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5679   PetscValidType(mat, 1);
5680   MatCheckPreallocated(mat, 1);
5681   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5682   if (mat->assembled) {
5683     mat->was_assembled = PETSC_TRUE;
5684     mat->assembled     = PETSC_FALSE;
5685   }
5686 
5687   if (!MatAssemblyEnd_InUse) {
5688     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5689     PetscTryTypeMethod(mat, assemblybegin, type);
5690     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5691   } else PetscTryTypeMethod(mat, assemblybegin, type);
5692   PetscFunctionReturn(PETSC_SUCCESS);
5693 }
5694 
5695 /*@
5696   MatAssembled - Indicates if a matrix has been assembled and is ready for
5697   use; for example, in matrix-vector product.
5698 
5699   Not Collective
5700 
5701   Input Parameter:
5702 . mat - the matrix
5703 
5704   Output Parameter:
5705 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5706 
5707   Level: advanced
5708 
5709 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5710 @*/
5711 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5712 {
5713   PetscFunctionBegin;
5714   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5715   PetscValidBoolPointer(assembled, 2);
5716   *assembled = mat->assembled;
5717   PetscFunctionReturn(PETSC_SUCCESS);
5718 }
5719 
5720 /*@
5721   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5722   be called after `MatAssemblyBegin()`.
5723 
5724   Collective
5725 
5726   Input Parameters:
5727 + mat  - the matrix
5728 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5729 
5730   Options Database Keys:
5731 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5732 . -mat_view ::ascii_info_detail      - Prints more detailed info
5733 . -mat_view                          - Prints matrix in ASCII format
5734 . -mat_view ::ascii_matlab           - Prints matrix in Matlab format
5735 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5736 . -display <name>                    - Sets display name (default is host)
5737 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5738 . -mat_view socket                   - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5739 . -viewer_socket_machine <machine>   - Machine to use for socket
5740 . -viewer_socket_port <port>         - Port number to use for socket
5741 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5742 
5743   Level: beginner
5744 
5745 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5746 @*/
5747 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5748 {
5749   static PetscInt inassm = 0;
5750   PetscBool       flg    = PETSC_FALSE;
5751 
5752   PetscFunctionBegin;
5753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5754   PetscValidType(mat, 1);
5755 
5756   inassm++;
5757   MatAssemblyEnd_InUse++;
5758   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5759     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5760     PetscTryTypeMethod(mat, assemblyend, type);
5761     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5762   } else PetscTryTypeMethod(mat, assemblyend, type);
5763 
5764   /* Flush assembly is not a true assembly */
5765   if (type != MAT_FLUSH_ASSEMBLY) {
5766     if (mat->num_ass) {
5767       if (!mat->symmetry_eternal) {
5768         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5769         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5770       }
5771       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5772       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5773     }
5774     mat->num_ass++;
5775     mat->assembled        = PETSC_TRUE;
5776     mat->ass_nonzerostate = mat->nonzerostate;
5777   }
5778 
5779   mat->insertmode = NOT_SET_VALUES;
5780   MatAssemblyEnd_InUse--;
5781   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5782   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5783     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5784 
5785     if (mat->checksymmetryonassembly) {
5786       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5787       if (flg) {
5788         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5789       } else {
5790         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5791       }
5792     }
5793     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5794   }
5795   inassm--;
5796   PetscFunctionReturn(PETSC_SUCCESS);
5797 }
5798 
5799 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5800 /*@
5801   MatSetOption - Sets a parameter option for a matrix. Some options
5802   may be specific to certain storage formats.  Some options
5803   determine how values will be inserted (or added). Sorted,
5804   row-oriented input will generally assemble the fastest. The default
5805   is row-oriented.
5806 
5807   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5808 
5809   Input Parameters:
5810 + mat - the matrix
5811 . op  - the option, one of those listed below (and possibly others),
5812 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5813 
5814   Options Describing Matrix Structure:
5815 + `MAT_SPD`                         - symmetric positive definite
5816 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5817 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5818 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5819 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5820 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5821 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5822 
5823    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5824    do not need to be computed (usually at a high cost)
5825 
5826    Options For Use with `MatSetValues()`:
5827    Insert a logically dense subblock, which can be
5828 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5829 
5830    These options reflect the data you pass in with `MatSetValues()`; it has
5831    nothing to do with how the data is stored internally in the matrix
5832    data structure.
5833 
5834    When (re)assembling a matrix, we can restrict the input for
5835    efficiency/debugging purposes.  These options include
5836 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5837 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5838 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5839 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5840 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5841 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5842         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5843         performance for very large process counts.
5844 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5845         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5846         functions, instead sending only neighbor messages.
5847 
5848   Level: intermediate
5849 
5850   Notes:
5851   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5852 
5853   Some options are relevant only for particular matrix types and
5854   are thus ignored by others.  Other options are not supported by
5855   certain matrix types and will generate an error message if set.
5856 
5857   If using Fortran to compute a matrix, one may need to
5858   use the column-oriented option (or convert to the row-oriented
5859   format).
5860 
5861   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5862   that would generate a new entry in the nonzero structure is instead
5863   ignored.  Thus, if memory has not already been allocated for this particular
5864   data, then the insertion is ignored. For dense matrices, in which
5865   the entire array is allocated, no entries are ever ignored.
5866   Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5867 
5868   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5869   that would generate a new entry in the nonzero structure instead produces
5870   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
5871 
5872   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5873   that would generate a new entry that has not been preallocated will
5874   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5875   only.) This is a useful flag when debugging matrix memory preallocation.
5876   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5877 
5878   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5879   other processors should be dropped, rather than stashed.
5880   This is useful if you know that the "owning" processor is also
5881   always generating the correct matrix entries, so that PETSc need
5882   not transfer duplicate entries generated on another processor.
5883 
5884   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5885   searches during matrix assembly. When this flag is set, the hash table
5886   is created during the first matrix assembly. This hash table is
5887   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5888   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5889   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5890   supported by `MATMPIBAIJ` format only.
5891 
5892   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5893   are kept in the nonzero structure
5894 
5895   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5896   a zero location in the matrix
5897 
5898   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5899 
5900   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5901   zero row routines and thus improves performance for very large process counts.
5902 
5903   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5904   part of the matrix (since they should match the upper triangular part).
5905 
5906   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5907   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5908   with finite difference schemes with non-periodic boundary conditions.
5909 
5910   Developer Notes:
5911   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5912   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5913   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5914   not changed.
5915 
5916 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5917 @*/
5918 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5919 {
5920   PetscFunctionBegin;
5921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5922   if (op > 0) {
5923     PetscValidLogicalCollectiveEnum(mat, op, 2);
5924     PetscValidLogicalCollectiveBool(mat, flg, 3);
5925   }
5926 
5927   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);
5928 
5929   switch (op) {
5930   case MAT_FORCE_DIAGONAL_ENTRIES:
5931     mat->force_diagonals = flg;
5932     PetscFunctionReturn(PETSC_SUCCESS);
5933   case MAT_NO_OFF_PROC_ENTRIES:
5934     mat->nooffprocentries = flg;
5935     PetscFunctionReturn(PETSC_SUCCESS);
5936   case MAT_SUBSET_OFF_PROC_ENTRIES:
5937     mat->assembly_subset = flg;
5938     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5939 #if !defined(PETSC_HAVE_MPIUNI)
5940       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5941 #endif
5942       mat->stash.first_assembly_done = PETSC_FALSE;
5943     }
5944     PetscFunctionReturn(PETSC_SUCCESS);
5945   case MAT_NO_OFF_PROC_ZERO_ROWS:
5946     mat->nooffproczerorows = flg;
5947     PetscFunctionReturn(PETSC_SUCCESS);
5948   case MAT_SPD:
5949     if (flg) {
5950       mat->spd                    = PETSC_BOOL3_TRUE;
5951       mat->symmetric              = PETSC_BOOL3_TRUE;
5952       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5953     } else {
5954       mat->spd = PETSC_BOOL3_FALSE;
5955     }
5956     break;
5957   case MAT_SYMMETRIC:
5958     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5959     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5960 #if !defined(PETSC_USE_COMPLEX)
5961     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5962 #endif
5963     break;
5964   case MAT_HERMITIAN:
5965     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5966     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5967 #if !defined(PETSC_USE_COMPLEX)
5968     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5969 #endif
5970     break;
5971   case MAT_STRUCTURALLY_SYMMETRIC:
5972     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5973     break;
5974   case MAT_SYMMETRY_ETERNAL:
5975     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");
5976     mat->symmetry_eternal = flg;
5977     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5978     break;
5979   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5980     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5981     mat->structural_symmetry_eternal = flg;
5982     break;
5983   case MAT_SPD_ETERNAL:
5984     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");
5985     mat->spd_eternal = flg;
5986     if (flg) {
5987       mat->structural_symmetry_eternal = PETSC_TRUE;
5988       mat->symmetry_eternal            = PETSC_TRUE;
5989     }
5990     break;
5991   case MAT_STRUCTURE_ONLY:
5992     mat->structure_only = flg;
5993     break;
5994   case MAT_SORTED_FULL:
5995     mat->sortedfull = flg;
5996     break;
5997   default:
5998     break;
5999   }
6000   PetscTryTypeMethod(mat, setoption, op, flg);
6001   PetscFunctionReturn(PETSC_SUCCESS);
6002 }
6003 
6004 /*@
6005   MatGetOption - Gets a parameter option that has been set for a matrix.
6006 
6007   Logically Collective
6008 
6009   Input Parameters:
6010 + mat - the matrix
6011 - op  - the option, this only responds to certain options, check the code for which ones
6012 
6013   Output Parameter:
6014 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6015 
6016   Level: intermediate
6017 
6018   Notes:
6019   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6020 
6021   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6022   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6023 
6024 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6025     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6026 @*/
6027 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6028 {
6029   PetscFunctionBegin;
6030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6031   PetscValidType(mat, 1);
6032 
6033   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);
6034   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()");
6035 
6036   switch (op) {
6037   case MAT_NO_OFF_PROC_ENTRIES:
6038     *flg = mat->nooffprocentries;
6039     break;
6040   case MAT_NO_OFF_PROC_ZERO_ROWS:
6041     *flg = mat->nooffproczerorows;
6042     break;
6043   case MAT_SYMMETRIC:
6044     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6045     break;
6046   case MAT_HERMITIAN:
6047     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6048     break;
6049   case MAT_STRUCTURALLY_SYMMETRIC:
6050     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6051     break;
6052   case MAT_SPD:
6053     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6054     break;
6055   case MAT_SYMMETRY_ETERNAL:
6056     *flg = mat->symmetry_eternal;
6057     break;
6058   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6059     *flg = mat->symmetry_eternal;
6060     break;
6061   default:
6062     break;
6063   }
6064   PetscFunctionReturn(PETSC_SUCCESS);
6065 }
6066 
6067 /*@
6068   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6069   this routine retains the old nonzero structure.
6070 
6071   Logically Collective
6072 
6073   Input Parameter:
6074 . mat - the matrix
6075 
6076   Level: intermediate
6077 
6078   Note:
6079   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.
6080   See the Performance chapter of the users manual for information on preallocating matrices.
6081 
6082 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6083 @*/
6084 PetscErrorCode MatZeroEntries(Mat mat)
6085 {
6086   PetscFunctionBegin;
6087   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6088   PetscValidType(mat, 1);
6089   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6090   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");
6091   MatCheckPreallocated(mat, 1);
6092 
6093   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6094   PetscUseTypeMethod(mat, zeroentries);
6095   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6096   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6097   PetscFunctionReturn(PETSC_SUCCESS);
6098 }
6099 
6100 /*@
6101   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6102   of a set of rows and columns of a matrix.
6103 
6104   Collective
6105 
6106   Input Parameters:
6107 + mat     - the matrix
6108 . numRows - the number of rows/columns to zero
6109 . rows    - the global row indices
6110 . diag    - value put in the diagonal of the eliminated rows
6111 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6112 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6113 
6114   Level: intermediate
6115 
6116   Notes:
6117   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6118 
6119   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6120   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
6121 
6122   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6123   Krylov method to take advantage of the known solution on the zeroed rows.
6124 
6125   For the parallel case, all processes that share the matrix (i.e.,
6126   those in the communicator used for matrix creation) MUST call this
6127   routine, regardless of whether any rows being zeroed are owned by
6128   them.
6129 
6130   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6131 
6132   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6133   list only rows local to itself).
6134 
6135   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6136 
6137 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6138           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6139 @*/
6140 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6141 {
6142   PetscFunctionBegin;
6143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6144   PetscValidType(mat, 1);
6145   if (numRows) PetscValidIntPointer(rows, 3);
6146   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6147   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6148   MatCheckPreallocated(mat, 1);
6149 
6150   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6151   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6152   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6153   PetscFunctionReturn(PETSC_SUCCESS);
6154 }
6155 
6156 /*@
6157   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6158   of a set of rows and columns of a matrix.
6159 
6160   Collective
6161 
6162   Input Parameters:
6163 + mat  - the matrix
6164 . is   - the rows to zero
6165 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6166 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6167 - b    - optional vector of right hand side, that will be adjusted by provided solution
6168 
6169   Level: intermediate
6170 
6171   Note:
6172   See `MatZeroRowsColumns()` for details on how this routine operates.
6173 
6174 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6175           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6176 @*/
6177 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6178 {
6179   PetscInt        numRows;
6180   const PetscInt *rows;
6181 
6182   PetscFunctionBegin;
6183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6184   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6185   PetscValidType(mat, 1);
6186   PetscValidType(is, 2);
6187   PetscCall(ISGetLocalSize(is, &numRows));
6188   PetscCall(ISGetIndices(is, &rows));
6189   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6190   PetscCall(ISRestoreIndices(is, &rows));
6191   PetscFunctionReturn(PETSC_SUCCESS);
6192 }
6193 
6194 /*@
6195   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6196   of a set of rows of a matrix.
6197 
6198   Collective
6199 
6200   Input Parameters:
6201 + mat     - the matrix
6202 . numRows - the number of rows to zero
6203 . rows    - the global row indices
6204 . diag    - value put in the diagonal of the zeroed rows
6205 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6206 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6207 
6208   Level: intermediate
6209 
6210   Notes:
6211   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6212 
6213   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6214 
6215   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6216   Krylov method to take advantage of the known solution on the zeroed rows.
6217 
6218   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)
6219   from the matrix.
6220 
6221   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6222   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
6223   formats this does not alter the nonzero structure.
6224 
6225   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6226   of the matrix is not changed the values are
6227   merely zeroed.
6228 
6229   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6230   formats can optionally remove the main diagonal entry from the
6231   nonzero structure as well, by passing 0.0 as the final argument).
6232 
6233   For the parallel case, all processes that share the matrix (i.e.,
6234   those in the communicator used for matrix creation) MUST call this
6235   routine, regardless of whether any rows being zeroed are owned by
6236   them.
6237 
6238   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6239   list only rows local to itself).
6240 
6241   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6242   owns that are to be zeroed. This saves a global synchronization in the implementation.
6243 
6244 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6245           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6246 @*/
6247 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6248 {
6249   PetscFunctionBegin;
6250   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6251   PetscValidType(mat, 1);
6252   if (numRows) PetscValidIntPointer(rows, 3);
6253   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6254   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6255   MatCheckPreallocated(mat, 1);
6256 
6257   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6258   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6259   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6260   PetscFunctionReturn(PETSC_SUCCESS);
6261 }
6262 
6263 /*@
6264   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6265   of a set of rows of a matrix.
6266 
6267   Collective
6268 
6269   Input Parameters:
6270 + mat  - the matrix
6271 . is   - index set of rows to remove (if `NULL` then no row is removed)
6272 . diag - value put in all diagonals of eliminated rows
6273 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6274 - b    - optional vector of right hand side, that will be adjusted by provided solution
6275 
6276   Level: intermediate
6277 
6278   Note:
6279   See `MatZeroRows()` for details on how this routine operates.
6280 
6281 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6282           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6283 @*/
6284 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6285 {
6286   PetscInt        numRows = 0;
6287   const PetscInt *rows    = NULL;
6288 
6289   PetscFunctionBegin;
6290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6291   PetscValidType(mat, 1);
6292   if (is) {
6293     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6294     PetscCall(ISGetLocalSize(is, &numRows));
6295     PetscCall(ISGetIndices(is, &rows));
6296   }
6297   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6298   if (is) PetscCall(ISRestoreIndices(is, &rows));
6299   PetscFunctionReturn(PETSC_SUCCESS);
6300 }
6301 
6302 /*@
6303   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6304   of a set of rows of a matrix. These rows must be local to the process.
6305 
6306   Collective
6307 
6308   Input Parameters:
6309 + mat     - the matrix
6310 . numRows - the number of rows to remove
6311 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6312 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6313 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6314 - b       - optional vector of right hand side, that will be adjusted by provided solution
6315 
6316   Level: intermediate
6317 
6318   Notes:
6319   See `MatZeroRows()` for details on how this routine operates.
6320 
6321   The grid coordinates are across the entire grid, not just the local portion
6322 
6323   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6324   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6325   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6326   `DM_BOUNDARY_PERIODIC` boundary type.
6327 
6328   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
6329   a single value per point) you can skip filling those indices.
6330 
6331   Fortran Notes:
6332   `idxm` and `idxn` should be declared as
6333 $     MatStencil idxm(4, m)
6334   and the values inserted using
6335 .vb
6336     idxm(MatStencil_i, 1) = i
6337     idxm(MatStencil_j, 1) = j
6338     idxm(MatStencil_k, 1) = k
6339     idxm(MatStencil_c, 1) = c
6340    etc
6341 .ve
6342 
6343 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6344           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6345 @*/
6346 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6347 {
6348   PetscInt  dim    = mat->stencil.dim;
6349   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6350   PetscInt *dims   = mat->stencil.dims + 1;
6351   PetscInt *starts = mat->stencil.starts;
6352   PetscInt *dxm    = (PetscInt *)rows;
6353   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6354 
6355   PetscFunctionBegin;
6356   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6357   PetscValidType(mat, 1);
6358   if (numRows) PetscValidPointer(rows, 3);
6359 
6360   PetscCall(PetscMalloc1(numRows, &jdxm));
6361   for (i = 0; i < numRows; ++i) {
6362     /* Skip unused dimensions (they are ordered k, j, i, c) */
6363     for (j = 0; j < 3 - sdim; ++j) dxm++;
6364     /* Local index in X dir */
6365     tmp = *dxm++ - starts[0];
6366     /* Loop over remaining dimensions */
6367     for (j = 0; j < dim - 1; ++j) {
6368       /* If nonlocal, set index to be negative */
6369       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6370       /* Update local index */
6371       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6372     }
6373     /* Skip component slot if necessary */
6374     if (mat->stencil.noc) dxm++;
6375     /* Local row number */
6376     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6377   }
6378   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6379   PetscCall(PetscFree(jdxm));
6380   PetscFunctionReturn(PETSC_SUCCESS);
6381 }
6382 
6383 /*@
6384   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6385   of a set of rows and columns of a matrix.
6386 
6387   Collective
6388 
6389   Input Parameters:
6390 + mat     - the matrix
6391 . numRows - the number of rows/columns to remove
6392 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6393 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6394 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6395 - b       - optional vector of right hand side, that will be adjusted by provided solution
6396 
6397   Level: intermediate
6398 
6399   Notes:
6400   See `MatZeroRowsColumns()` for details on how this routine operates.
6401 
6402   The grid coordinates are across the entire grid, not just the local portion
6403 
6404   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6405   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6406   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6407   `DM_BOUNDARY_PERIODIC` boundary type.
6408 
6409   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
6410   a single value per point) you can skip filling those indices.
6411 
6412   Fortran Notes:
6413   `idxm` and `idxn` should be declared as
6414 $     MatStencil idxm(4, m)
6415   and the values inserted using
6416 .vb
6417     idxm(MatStencil_i, 1) = i
6418     idxm(MatStencil_j, 1) = j
6419     idxm(MatStencil_k, 1) = k
6420     idxm(MatStencil_c, 1) = c
6421     etc
6422 .ve
6423 
6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6425           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6426 @*/
6427 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6428 {
6429   PetscInt  dim    = mat->stencil.dim;
6430   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6431   PetscInt *dims   = mat->stencil.dims + 1;
6432   PetscInt *starts = mat->stencil.starts;
6433   PetscInt *dxm    = (PetscInt *)rows;
6434   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6435 
6436   PetscFunctionBegin;
6437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6438   PetscValidType(mat, 1);
6439   if (numRows) PetscValidPointer(rows, 3);
6440 
6441   PetscCall(PetscMalloc1(numRows, &jdxm));
6442   for (i = 0; i < numRows; ++i) {
6443     /* Skip unused dimensions (they are ordered k, j, i, c) */
6444     for (j = 0; j < 3 - sdim; ++j) dxm++;
6445     /* Local index in X dir */
6446     tmp = *dxm++ - starts[0];
6447     /* Loop over remaining dimensions */
6448     for (j = 0; j < dim - 1; ++j) {
6449       /* If nonlocal, set index to be negative */
6450       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6451       /* Update local index */
6452       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6453     }
6454     /* Skip component slot if necessary */
6455     if (mat->stencil.noc) dxm++;
6456     /* Local row number */
6457     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6458   }
6459   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6460   PetscCall(PetscFree(jdxm));
6461   PetscFunctionReturn(PETSC_SUCCESS);
6462 }
6463 
6464 /*@C
6465   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6466   of a set of rows of a matrix; using local numbering of rows.
6467 
6468   Collective
6469 
6470   Input Parameters:
6471 + mat     - the matrix
6472 . numRows - the number of rows to remove
6473 . rows    - the local row indices
6474 . diag    - value put in all diagonals of eliminated rows
6475 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6476 - b       - optional vector of right hand side, that will be adjusted by provided solution
6477 
6478   Level: intermediate
6479 
6480   Notes:
6481   Before calling `MatZeroRowsLocal()`, the user must first set the
6482   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6483 
6484   See `MatZeroRows()` for details on how this routine operates.
6485 
6486 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6487           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6488 @*/
6489 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6490 {
6491   PetscFunctionBegin;
6492   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6493   PetscValidType(mat, 1);
6494   if (numRows) PetscValidIntPointer(rows, 3);
6495   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6496   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6497   MatCheckPreallocated(mat, 1);
6498 
6499   if (mat->ops->zerorowslocal) {
6500     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6501   } else {
6502     IS              is, newis;
6503     const PetscInt *newRows;
6504 
6505     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6506     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6507     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6508     PetscCall(ISGetIndices(newis, &newRows));
6509     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6510     PetscCall(ISRestoreIndices(newis, &newRows));
6511     PetscCall(ISDestroy(&newis));
6512     PetscCall(ISDestroy(&is));
6513   }
6514   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6515   PetscFunctionReturn(PETSC_SUCCESS);
6516 }
6517 
6518 /*@
6519   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6520   of a set of rows of a matrix; using local numbering of rows.
6521 
6522   Collective
6523 
6524   Input Parameters:
6525 + mat  - the matrix
6526 . is   - index set of rows to remove
6527 . diag - value put in all diagonals of eliminated rows
6528 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6529 - b    - optional vector of right hand side, that will be adjusted by provided solution
6530 
6531   Level: intermediate
6532 
6533   Notes:
6534   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6535   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6536 
6537   See `MatZeroRows()` for details on how this routine operates.
6538 
6539 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6540           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6541 @*/
6542 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6543 {
6544   PetscInt        numRows;
6545   const PetscInt *rows;
6546 
6547   PetscFunctionBegin;
6548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6549   PetscValidType(mat, 1);
6550   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6551   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6552   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6553   MatCheckPreallocated(mat, 1);
6554 
6555   PetscCall(ISGetLocalSize(is, &numRows));
6556   PetscCall(ISGetIndices(is, &rows));
6557   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6558   PetscCall(ISRestoreIndices(is, &rows));
6559   PetscFunctionReturn(PETSC_SUCCESS);
6560 }
6561 
6562 /*@
6563   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6564   of a set of rows and columns of a matrix; using local numbering of rows.
6565 
6566   Collective
6567 
6568   Input Parameters:
6569 + mat     - the matrix
6570 . numRows - the number of rows to remove
6571 . rows    - the global row indices
6572 . diag    - value put in all diagonals of eliminated rows
6573 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6574 - b       - optional vector of right hand side, that will be adjusted by provided solution
6575 
6576   Level: intermediate
6577 
6578   Notes:
6579   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6580   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6581 
6582   See `MatZeroRowsColumns()` for details on how this routine operates.
6583 
6584 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6585           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6586 @*/
6587 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6588 {
6589   IS              is, newis;
6590   const PetscInt *newRows;
6591 
6592   PetscFunctionBegin;
6593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6594   PetscValidType(mat, 1);
6595   if (numRows) PetscValidIntPointer(rows, 3);
6596   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6597   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6598   MatCheckPreallocated(mat, 1);
6599 
6600   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6601   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6602   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6603   PetscCall(ISGetIndices(newis, &newRows));
6604   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6605   PetscCall(ISRestoreIndices(newis, &newRows));
6606   PetscCall(ISDestroy(&newis));
6607   PetscCall(ISDestroy(&is));
6608   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6609   PetscFunctionReturn(PETSC_SUCCESS);
6610 }
6611 
6612 /*@
6613   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6614   of a set of rows and columns of a matrix; using local numbering of rows.
6615 
6616   Collective
6617 
6618   Input Parameters:
6619 + mat  - the matrix
6620 . is   - index set of rows to remove
6621 . diag - value put in all diagonals of eliminated rows
6622 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6623 - b    - optional vector of right hand side, that will be adjusted by provided solution
6624 
6625   Level: intermediate
6626 
6627   Notes:
6628   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6629   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6630 
6631   See `MatZeroRowsColumns()` for details on how this routine operates.
6632 
6633 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6634           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6635 @*/
6636 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6637 {
6638   PetscInt        numRows;
6639   const PetscInt *rows;
6640 
6641   PetscFunctionBegin;
6642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6643   PetscValidType(mat, 1);
6644   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6645   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6646   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6647   MatCheckPreallocated(mat, 1);
6648 
6649   PetscCall(ISGetLocalSize(is, &numRows));
6650   PetscCall(ISGetIndices(is, &rows));
6651   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6652   PetscCall(ISRestoreIndices(is, &rows));
6653   PetscFunctionReturn(PETSC_SUCCESS);
6654 }
6655 
6656 /*@C
6657   MatGetSize - Returns the numbers of rows and columns in a matrix.
6658 
6659   Not Collective
6660 
6661   Input Parameter:
6662 . mat - the matrix
6663 
6664   Output Parameters:
6665 + m - the number of global rows
6666 - n - the number of global columns
6667 
6668   Level: beginner
6669 
6670   Note:
6671   Both output parameters can be `NULL` on input.
6672 
6673 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6674 @*/
6675 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6676 {
6677   PetscFunctionBegin;
6678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6679   if (m) *m = mat->rmap->N;
6680   if (n) *n = mat->cmap->N;
6681   PetscFunctionReturn(PETSC_SUCCESS);
6682 }
6683 
6684 /*@C
6685   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6686   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6687 
6688   Not Collective
6689 
6690   Input Parameter:
6691 . mat - the matrix
6692 
6693   Output Parameters:
6694 + m - the number of local rows, use `NULL` to not obtain this value
6695 - n - the number of local columns, use `NULL` to not obtain this value
6696 
6697   Level: beginner
6698 
6699 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6700 @*/
6701 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6702 {
6703   PetscFunctionBegin;
6704   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6705   if (m) PetscValidIntPointer(m, 2);
6706   if (n) PetscValidIntPointer(n, 3);
6707   if (m) *m = mat->rmap->n;
6708   if (n) *n = mat->cmap->n;
6709   PetscFunctionReturn(PETSC_SUCCESS);
6710 }
6711 
6712 /*@C
6713   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6714   vector one multiplies this matrix by that are owned by this processor.
6715 
6716   Not Collective, unless matrix has not been allocated, then collective
6717 
6718   Input Parameter:
6719 . mat - the matrix
6720 
6721   Output Parameters:
6722 + m - the global index of the first local column, use `NULL` to not obtain this value
6723 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6724 
6725   Level: developer
6726 
6727   Notes:
6728   Retursns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6729   Layouts](sec_matlayout) for details on matrix layouts.
6730 
6731 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6732 @*/
6733 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6734 {
6735   PetscFunctionBegin;
6736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6737   PetscValidType(mat, 1);
6738   if (m) PetscValidIntPointer(m, 2);
6739   if (n) PetscValidIntPointer(n, 3);
6740   MatCheckPreallocated(mat, 1);
6741   if (m) *m = mat->cmap->rstart;
6742   if (n) *n = mat->cmap->rend;
6743   PetscFunctionReturn(PETSC_SUCCESS);
6744 }
6745 
6746 /*@C
6747   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6748   this MPI process.
6749 
6750   Not Collective
6751 
6752   Input Parameter:
6753 . mat - the matrix
6754 
6755   Output Parameters:
6756 + m - the global index of the first local row, use `NULL` to not obtain this value
6757 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6758 
6759   Level: beginner
6760 
6761   Note:
6762   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6763   would contain the result of a matrix vector product with this matrix. See [Matrix
6764   Layouts](sec_matlayout) for details on matrix layouts.
6765 
6766 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6767           `PetscLayout`
6768 @*/
6769 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6770 {
6771   PetscFunctionBegin;
6772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6773   PetscValidType(mat, 1);
6774   if (m) PetscValidIntPointer(m, 2);
6775   if (n) PetscValidIntPointer(n, 3);
6776   MatCheckPreallocated(mat, 1);
6777   if (m) *m = mat->rmap->rstart;
6778   if (n) *n = mat->rmap->rend;
6779   PetscFunctionReturn(PETSC_SUCCESS);
6780 }
6781 
6782 /*@C
6783   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6784   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6785 
6786   Not Collective, unless matrix has not been allocated
6787 
6788   Input Parameter:
6789 . mat - the matrix
6790 
6791   Output Parameter:
6792 . ranges - start of each processors portion plus one more than the total length at the end
6793 
6794   Level: beginner
6795 
6796   Notes:
6797   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6798   would contain the result of a matrix vector product with this matrix. See [Matrix
6799   Layouts](sec_matlayout) for details on matrix layouts.
6800 
6801 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6802 @*/
6803 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6804 {
6805   PetscFunctionBegin;
6806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6807   PetscValidType(mat, 1);
6808   MatCheckPreallocated(mat, 1);
6809   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6810   PetscFunctionReturn(PETSC_SUCCESS);
6811 }
6812 
6813 /*@C
6814   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6815   vector one multiplies this vector by that are owned by each processor.
6816 
6817   Not Collective, unless matrix has not been allocated
6818 
6819   Input Parameter:
6820 . mat - the matrix
6821 
6822   Output Parameter:
6823 . ranges - start of each processors portion plus one more then the total length at the end
6824 
6825   Level: beginner
6826 
6827   Notes:
6828   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6829   Layouts](sec_matlayout) for details on matrix layouts.
6830 
6831 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6832 @*/
6833 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6834 {
6835   PetscFunctionBegin;
6836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6837   PetscValidType(mat, 1);
6838   MatCheckPreallocated(mat, 1);
6839   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6840   PetscFunctionReturn(PETSC_SUCCESS);
6841 }
6842 
6843 /*@C
6844   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6845 
6846   Not Collective
6847 
6848   Input Parameter:
6849 . A - matrix
6850 
6851   Output Parameters:
6852 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6853 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6854 
6855   Level: intermediate
6856 
6857   Notes:
6858   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6859   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6860   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6861   details on matrix layouts.
6862 
6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6864 @*/
6865 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6866 {
6867   PetscErrorCode (*f)(Mat, IS *, IS *);
6868 
6869   PetscFunctionBegin;
6870   MatCheckPreallocated(A, 1);
6871   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6872   if (f) {
6873     PetscCall((*f)(A, rows, cols));
6874   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6875     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6876     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6877   }
6878   PetscFunctionReturn(PETSC_SUCCESS);
6879 }
6880 
6881 /*@C
6882   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6883   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6884   to complete the factorization.
6885 
6886   Collective
6887 
6888   Input Parameters:
6889 + fact - the factorized matrix obtained with `MatGetFactor()`
6890 . mat  - the matrix
6891 . row  - row permutation
6892 . col  - column permutation
6893 - info - structure containing
6894 .vb
6895       levels - number of levels of fill.
6896       expected fill - as ratio of original fill.
6897       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6898                 missing diagonal entries)
6899 .ve
6900 
6901   Level: developer
6902 
6903   Notes:
6904   See [Matrix Factorization](sec_matfactor) for additional information.
6905 
6906   Most users should employ the `KSP` interface for linear solvers
6907   instead of working directly with matrix algebra routines such as this.
6908   See, e.g., `KSPCreate()`.
6909 
6910   Uses the definition of level of fill as in Y. Saad, 2003
6911 
6912   Developer Notes:
6913   The Fortran interface is not autogenerated as the
6914   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6915 
6916   References:
6917 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6918 
6919 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6920           `MatGetOrdering()`, `MatFactorInfo`
6921 @*/
6922 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6923 {
6924   PetscFunctionBegin;
6925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6926   PetscValidType(mat, 2);
6927   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6928   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6929   PetscValidPointer(info, 5);
6930   PetscValidPointer(fact, 1);
6931   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6932   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6933   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6934   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6935   MatCheckPreallocated(mat, 2);
6936 
6937   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6938   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6939   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6940   PetscFunctionReturn(PETSC_SUCCESS);
6941 }
6942 
6943 /*@C
6944   MatICCFactorSymbolic - Performs symbolic incomplete
6945   Cholesky factorization for a symmetric matrix.  Use
6946   `MatCholeskyFactorNumeric()` to complete the factorization.
6947 
6948   Collective
6949 
6950   Input Parameters:
6951 + fact - the factorized matrix obtained with `MatGetFactor()`
6952 . mat  - the matrix to be factored
6953 . perm - row and column permutation
6954 - info - structure containing
6955 .vb
6956       levels - number of levels of fill.
6957       expected fill - as ratio of original fill.
6958 .ve
6959 
6960   Level: developer
6961 
6962   Notes:
6963   Most users should employ the `KSP` interface for linear solvers
6964   instead of working directly with matrix algebra routines such as this.
6965   See, e.g., `KSPCreate()`.
6966 
6967   This uses the definition of level of fill as in Y. Saad, 2003
6968 
6969   Developer Notes:
6970   The Fortran interface is not autogenerated as the
6971   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6972 
6973   References:
6974 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6975 
6976 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6977 @*/
6978 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6979 {
6980   PetscFunctionBegin;
6981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6982   PetscValidType(mat, 2);
6983   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6984   PetscValidPointer(info, 4);
6985   PetscValidPointer(fact, 1);
6986   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6987   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6988   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6989   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6990   MatCheckPreallocated(mat, 2);
6991 
6992   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6993   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6994   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6995   PetscFunctionReturn(PETSC_SUCCESS);
6996 }
6997 
6998 /*@C
6999   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7000   points to an array of valid matrices, they may be reused to store the new
7001   submatrices.
7002 
7003   Collective
7004 
7005   Input Parameters:
7006 + mat   - the matrix
7007 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7008 . irow  - index set of rows to extract
7009 . icol  - index set of columns to extract
7010 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7011 
7012   Output Parameter:
7013 . submat - the array of submatrices
7014 
7015   Level: advanced
7016 
7017   Notes:
7018   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7019   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7020   to extract a parallel submatrix.
7021 
7022   Some matrix types place restrictions on the row and column
7023   indices, such as that they be sorted or that they be equal to each other.
7024 
7025   The index sets may not have duplicate entries.
7026 
7027   When extracting submatrices from a parallel matrix, each processor can
7028   form a different submatrix by setting the rows and columns of its
7029   individual index sets according to the local submatrix desired.
7030 
7031   When finished using the submatrices, the user should destroy
7032   them with `MatDestroySubMatrices()`.
7033 
7034   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7035   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7036 
7037   This routine creates the matrices in submat; you should NOT create them before
7038   calling it. It also allocates the array of matrix pointers submat.
7039 
7040   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7041   request one row/column in a block, they must request all rows/columns that are in
7042   that block. For example, if the block size is 2 you cannot request just row 0 and
7043   column 0.
7044 
7045   Fortran Notes:
7046   The Fortran interface is slightly different from that given below; it
7047   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7048 
7049 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7050 @*/
7051 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7052 {
7053   PetscInt  i;
7054   PetscBool eq;
7055 
7056   PetscFunctionBegin;
7057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7058   PetscValidType(mat, 1);
7059   if (n) {
7060     PetscValidPointer(irow, 3);
7061     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7062     PetscValidPointer(icol, 4);
7063     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7064   }
7065   PetscValidPointer(submat, 6);
7066   if (n && scall == MAT_REUSE_MATRIX) {
7067     PetscValidPointer(*submat, 6);
7068     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7069   }
7070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7071   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7072   MatCheckPreallocated(mat, 1);
7073   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7074   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7075   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7076   for (i = 0; i < n; i++) {
7077     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7078     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7079     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7080 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7081     if (mat->boundtocpu && mat->bindingpropagates) {
7082       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7083       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7084     }
7085 #endif
7086   }
7087   PetscFunctionReturn(PETSC_SUCCESS);
7088 }
7089 
7090 /*@C
7091   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7092 
7093   Collective
7094 
7095   Input Parameters:
7096 + mat   - the matrix
7097 . n     - the number of submatrixes to be extracted
7098 . irow  - index set of rows to extract
7099 . icol  - index set of columns to extract
7100 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7101 
7102   Output Parameter:
7103 . submat - the array of submatrices
7104 
7105   Level: advanced
7106 
7107   Note:
7108   This is used by `PCGASM`
7109 
7110 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7111 @*/
7112 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7113 {
7114   PetscInt  i;
7115   PetscBool eq;
7116 
7117   PetscFunctionBegin;
7118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7119   PetscValidType(mat, 1);
7120   if (n) {
7121     PetscValidPointer(irow, 3);
7122     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7123     PetscValidPointer(icol, 4);
7124     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7125   }
7126   PetscValidPointer(submat, 6);
7127   if (n && scall == MAT_REUSE_MATRIX) {
7128     PetscValidPointer(*submat, 6);
7129     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7130   }
7131   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7132   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7133   MatCheckPreallocated(mat, 1);
7134 
7135   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7136   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7137   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7138   for (i = 0; i < n; i++) {
7139     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7140     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7141   }
7142   PetscFunctionReturn(PETSC_SUCCESS);
7143 }
7144 
7145 /*@C
7146   MatDestroyMatrices - Destroys an array of matrices.
7147 
7148   Collective
7149 
7150   Input Parameters:
7151 + n   - the number of local matrices
7152 - mat - the matrices (this is a pointer to the array of matrices)
7153 
7154   Level: advanced
7155 
7156   Note:
7157   Frees not only the matrices, but also the array that contains the matrices
7158 
7159   Fortran Notes:
7160   This does not free the array.
7161 
7162 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7163 @*/
7164 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7165 {
7166   PetscInt i;
7167 
7168   PetscFunctionBegin;
7169   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7170   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7171   PetscValidPointer(mat, 2);
7172 
7173   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7174 
7175   /* memory is allocated even if n = 0 */
7176   PetscCall(PetscFree(*mat));
7177   PetscFunctionReturn(PETSC_SUCCESS);
7178 }
7179 
7180 /*@C
7181   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7182 
7183   Collective
7184 
7185   Input Parameters:
7186 + n   - the number of local matrices
7187 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7188                        sequence of `MatCreateSubMatrices()`)
7189 
7190   Level: advanced
7191 
7192   Note:
7193   Frees not only the matrices, but also the array that contains the matrices
7194 
7195   Fortran Notes:
7196   This does not free the array.
7197 
7198 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7199 @*/
7200 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7201 {
7202   Mat mat0;
7203 
7204   PetscFunctionBegin;
7205   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7206   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7207   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7208   PetscValidPointer(mat, 2);
7209 
7210   mat0 = (*mat)[0];
7211   if (mat0 && mat0->ops->destroysubmatrices) {
7212     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7213   } else {
7214     PetscCall(MatDestroyMatrices(n, mat));
7215   }
7216   PetscFunctionReturn(PETSC_SUCCESS);
7217 }
7218 
7219 /*@C
7220   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7221 
7222   Collective
7223 
7224   Input Parameter:
7225 . mat - the matrix
7226 
7227   Output Parameter:
7228 . matstruct - the sequential matrix with the nonzero structure of mat
7229 
7230   Level: developer
7231 
7232 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7233 @*/
7234 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7235 {
7236   PetscFunctionBegin;
7237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7238   PetscValidPointer(matstruct, 2);
7239 
7240   PetscValidType(mat, 1);
7241   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7242   MatCheckPreallocated(mat, 1);
7243 
7244   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7245   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7246   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7247   PetscFunctionReturn(PETSC_SUCCESS);
7248 }
7249 
7250 /*@C
7251   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7252 
7253   Collective
7254 
7255   Input Parameter:
7256 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7257                        sequence of `MatGetSeqNonzeroStructure()`)
7258 
7259   Level: advanced
7260 
7261   Note:
7262   Frees not only the matrices, but also the array that contains the matrices
7263 
7264 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7265 @*/
7266 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7267 {
7268   PetscFunctionBegin;
7269   PetscValidPointer(mat, 1);
7270   PetscCall(MatDestroy(mat));
7271   PetscFunctionReturn(PETSC_SUCCESS);
7272 }
7273 
7274 /*@
7275   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7276   replaces the index sets by larger ones that represent submatrices with
7277   additional overlap.
7278 
7279   Collective
7280 
7281   Input Parameters:
7282 + mat - the matrix
7283 . n   - the number of index sets
7284 . is  - the array of index sets (these index sets will changed during the call)
7285 - ov  - the additional overlap requested
7286 
7287   Options Database Key:
7288 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7289 
7290   Level: developer
7291 
7292   Note:
7293   The computed overlap preserves the matrix block sizes when the blocks are square.
7294   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7295   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7296 
7297 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7298 @*/
7299 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7300 {
7301   PetscInt i, bs, cbs;
7302 
7303   PetscFunctionBegin;
7304   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7305   PetscValidType(mat, 1);
7306   PetscValidLogicalCollectiveInt(mat, n, 2);
7307   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7308   if (n) {
7309     PetscValidPointer(is, 3);
7310     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7311   }
7312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7314   MatCheckPreallocated(mat, 1);
7315 
7316   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7317   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7318   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7319   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7320   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7321   if (bs == cbs) {
7322     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7323   }
7324   PetscFunctionReturn(PETSC_SUCCESS);
7325 }
7326 
7327 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7328 
7329 /*@
7330   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7331   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7332   additional overlap.
7333 
7334   Collective
7335 
7336   Input Parameters:
7337 + mat - the matrix
7338 . n   - the number of index sets
7339 . is  - the array of index sets (these index sets will changed during the call)
7340 - ov  - the additional overlap requested
7341 
7342   `   Options Database Key:
7343 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7344 
7345   Level: developer
7346 
7347 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7348 @*/
7349 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7350 {
7351   PetscInt i;
7352 
7353   PetscFunctionBegin;
7354   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7355   PetscValidType(mat, 1);
7356   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7357   if (n) {
7358     PetscValidPointer(is, 3);
7359     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7360   }
7361   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7362   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7363   MatCheckPreallocated(mat, 1);
7364   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7365   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7366   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7367   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7368   PetscFunctionReturn(PETSC_SUCCESS);
7369 }
7370 
7371 /*@
7372   MatGetBlockSize - Returns the matrix block size.
7373 
7374   Not Collective
7375 
7376   Input Parameter:
7377 . mat - the matrix
7378 
7379   Output Parameter:
7380 . bs - block size
7381 
7382   Level: intermediate
7383 
7384   Notes:
7385   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7386 
7387   If the block size has not been set yet this routine returns 1.
7388 
7389 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7390 @*/
7391 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7392 {
7393   PetscFunctionBegin;
7394   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7395   PetscValidIntPointer(bs, 2);
7396   *bs = PetscAbs(mat->rmap->bs);
7397   PetscFunctionReturn(PETSC_SUCCESS);
7398 }
7399 
7400 /*@
7401   MatGetBlockSizes - Returns the matrix block row and column sizes.
7402 
7403   Not Collective
7404 
7405   Input Parameter:
7406 . mat - the matrix
7407 
7408   Output Parameters:
7409 + rbs - row block size
7410 - cbs - column block size
7411 
7412   Level: intermediate
7413 
7414   Notes:
7415   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7416   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7417 
7418   If a block size has not been set yet this routine returns 1.
7419 
7420 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7421 @*/
7422 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7423 {
7424   PetscFunctionBegin;
7425   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7426   if (rbs) PetscValidIntPointer(rbs, 2);
7427   if (cbs) PetscValidIntPointer(cbs, 3);
7428   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7429   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7430   PetscFunctionReturn(PETSC_SUCCESS);
7431 }
7432 
7433 /*@
7434   MatSetBlockSize - Sets the matrix block size.
7435 
7436   Logically Collective
7437 
7438   Input Parameters:
7439 + mat - the matrix
7440 - bs  - block size
7441 
7442   Level: intermediate
7443 
7444   Notes:
7445   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7446   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7447 
7448   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7449   is compatible with the matrix local sizes.
7450 
7451 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7452 @*/
7453 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7454 {
7455   PetscFunctionBegin;
7456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7457   PetscValidLogicalCollectiveInt(mat, bs, 2);
7458   PetscCall(MatSetBlockSizes(mat, bs, bs));
7459   PetscFunctionReturn(PETSC_SUCCESS);
7460 }
7461 
7462 typedef struct {
7463   PetscInt         n;
7464   IS              *is;
7465   Mat             *mat;
7466   PetscObjectState nonzerostate;
7467   Mat              C;
7468 } EnvelopeData;
7469 
7470 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7471 {
7472   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7473   PetscCall(PetscFree(edata->is));
7474   PetscCall(PetscFree(edata));
7475   return PETSC_SUCCESS;
7476 }
7477 
7478 /*
7479    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7480          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7481 
7482    Collective
7483 
7484    Input Parameter:
7485 .  mat - the matrix
7486 
7487    Notes:
7488      There can be zeros within the blocks
7489 
7490      The blocks can overlap between processes, including laying on more than two processes
7491 
7492 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7493 */
7494 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7495 {
7496   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7497   PetscInt          *diag, *odiag, sc;
7498   VecScatter         scatter;
7499   PetscScalar       *seqv;
7500   const PetscScalar *parv;
7501   const PetscInt    *ia, *ja;
7502   PetscBool          set, flag, done;
7503   Mat                AA = mat, A;
7504   MPI_Comm           comm;
7505   PetscMPIInt        rank, size, tag;
7506   MPI_Status         status;
7507   PetscContainer     container;
7508   EnvelopeData      *edata;
7509   Vec                seq, par;
7510   IS                 isglobal;
7511 
7512   PetscFunctionBegin;
7513   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7514   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7515   if (!set || !flag) {
7516     /* TODO: only needs nonzero structure of transpose */
7517     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7518     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7519   }
7520   PetscCall(MatAIJGetLocalMat(AA, &A));
7521   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7522   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7523 
7524   PetscCall(MatGetLocalSize(mat, &n, NULL));
7525   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7526   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7527   PetscCallMPI(MPI_Comm_size(comm, &size));
7528   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7529 
7530   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7531 
7532   if (rank > 0) {
7533     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7534     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7535   }
7536   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7537   for (i = 0; i < n; i++) {
7538     env = PetscMax(env, ja[ia[i + 1] - 1]);
7539     II  = rstart + i;
7540     if (env == II) {
7541       starts[lblocks]  = tbs;
7542       sizes[lblocks++] = 1 + II - tbs;
7543       tbs              = 1 + II;
7544     }
7545   }
7546   if (rank < size - 1) {
7547     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7548     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7549   }
7550 
7551   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7552   if (!set || !flag) PetscCall(MatDestroy(&AA));
7553   PetscCall(MatDestroy(&A));
7554 
7555   PetscCall(PetscNew(&edata));
7556   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7557   edata->n = lblocks;
7558   /* create IS needed for extracting blocks from the original matrix */
7559   PetscCall(PetscMalloc1(lblocks, &edata->is));
7560   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7561 
7562   /* Create the resulting inverse matrix structure with preallocation information */
7563   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7564   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7565   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7566   PetscCall(MatSetType(edata->C, MATAIJ));
7567 
7568   /* Communicate the start and end of each row, from each block to the correct rank */
7569   /* TODO: Use PetscSF instead of VecScatter */
7570   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7571   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7572   PetscCall(VecGetArrayWrite(seq, &seqv));
7573   for (PetscInt i = 0; i < lblocks; i++) {
7574     for (PetscInt j = 0; j < sizes[i]; j++) {
7575       seqv[cnt]     = starts[i];
7576       seqv[cnt + 1] = starts[i] + sizes[i];
7577       cnt += 2;
7578     }
7579   }
7580   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7581   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7582   sc -= cnt;
7583   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7584   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7585   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7586   PetscCall(ISDestroy(&isglobal));
7587   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7588   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7589   PetscCall(VecScatterDestroy(&scatter));
7590   PetscCall(VecDestroy(&seq));
7591   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7592   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7593   PetscCall(VecGetArrayRead(par, &parv));
7594   cnt = 0;
7595   PetscCall(MatGetSize(mat, NULL, &n));
7596   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7597     PetscInt start, end, d = 0, od = 0;
7598 
7599     start = (PetscInt)PetscRealPart(parv[cnt]);
7600     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7601     cnt += 2;
7602 
7603     if (start < cstart) {
7604       od += cstart - start + n - cend;
7605       d += cend - cstart;
7606     } else if (start < cend) {
7607       od += n - cend;
7608       d += cend - start;
7609     } else od += n - start;
7610     if (end <= cstart) {
7611       od -= cstart - end + n - cend;
7612       d -= cend - cstart;
7613     } else if (end < cend) {
7614       od -= n - cend;
7615       d -= cend - end;
7616     } else od -= n - end;
7617 
7618     odiag[i] = od;
7619     diag[i]  = d;
7620   }
7621   PetscCall(VecRestoreArrayRead(par, &parv));
7622   PetscCall(VecDestroy(&par));
7623   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7624   PetscCall(PetscFree2(diag, odiag));
7625   PetscCall(PetscFree2(sizes, starts));
7626 
7627   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7628   PetscCall(PetscContainerSetPointer(container, edata));
7629   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7630   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7631   PetscCall(PetscObjectDereference((PetscObject)container));
7632   PetscFunctionReturn(PETSC_SUCCESS);
7633 }
7634 
7635 /*@
7636   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7637 
7638   Collective
7639 
7640   Input Parameters:
7641 + A     - the matrix
7642 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7643 
7644   Output Parameter:
7645 . C - matrix with inverted block diagonal of `A`
7646 
7647   Level: advanced
7648 
7649   Note:
7650   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7651 
7652 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7653 @*/
7654 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7655 {
7656   PetscContainer   container;
7657   EnvelopeData    *edata;
7658   PetscObjectState nonzerostate;
7659 
7660   PetscFunctionBegin;
7661   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7662   if (!container) {
7663     PetscCall(MatComputeVariableBlockEnvelope(A));
7664     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7665   }
7666   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7667   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7668   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7669   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7670 
7671   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7672   *C = edata->C;
7673 
7674   for (PetscInt i = 0; i < edata->n; i++) {
7675     Mat          D;
7676     PetscScalar *dvalues;
7677 
7678     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7679     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7680     PetscCall(MatSeqDenseInvert(D));
7681     PetscCall(MatDenseGetArray(D, &dvalues));
7682     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7683     PetscCall(MatDestroy(&D));
7684   }
7685   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7686   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7687   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7688   PetscFunctionReturn(PETSC_SUCCESS);
7689 }
7690 
7691 /*@
7692   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7693 
7694   Logically Collective
7695 
7696   Input Parameters:
7697 + mat     - the matrix
7698 . nblocks - the number of blocks on this process, each block can only exist on a single process
7699 - bsizes  - the block sizes
7700 
7701   Level: intermediate
7702 
7703   Notes:
7704   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7705 
7706   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.
7707 
7708 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7709           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7710 @*/
7711 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7712 {
7713   PetscInt i, ncnt = 0, nlocal;
7714 
7715   PetscFunctionBegin;
7716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7717   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7718   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7719   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7720   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);
7721   PetscCall(PetscFree(mat->bsizes));
7722   mat->nblocks = nblocks;
7723   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7724   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7725   PetscFunctionReturn(PETSC_SUCCESS);
7726 }
7727 
7728 /*@C
7729   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7730 
7731   Logically Collective; No Fortran Support
7732 
7733   Input Parameter:
7734 . mat - the matrix
7735 
7736   Output Parameters:
7737 + nblocks - the number of blocks on this process
7738 - bsizes  - the block sizes
7739 
7740   Level: intermediate
7741 
7742 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7743 @*/
7744 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7745 {
7746   PetscFunctionBegin;
7747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7748   *nblocks = mat->nblocks;
7749   *bsizes  = mat->bsizes;
7750   PetscFunctionReturn(PETSC_SUCCESS);
7751 }
7752 
7753 /*@
7754   MatSetBlockSizes - Sets the matrix block row and column sizes.
7755 
7756   Logically Collective
7757 
7758   Input Parameters:
7759 + mat - the matrix
7760 . rbs - row block size
7761 - cbs - column block size
7762 
7763   Level: intermediate
7764 
7765   Notes:
7766   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7767   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7768   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7769 
7770   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7771   are compatible with the matrix local sizes.
7772 
7773   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7774 
7775 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7776 @*/
7777 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7778 {
7779   PetscFunctionBegin;
7780   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7781   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7782   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7783   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7784   if (mat->rmap->refcnt) {
7785     ISLocalToGlobalMapping l2g  = NULL;
7786     PetscLayout            nmap = NULL;
7787 
7788     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7789     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7790     PetscCall(PetscLayoutDestroy(&mat->rmap));
7791     mat->rmap          = nmap;
7792     mat->rmap->mapping = l2g;
7793   }
7794   if (mat->cmap->refcnt) {
7795     ISLocalToGlobalMapping l2g  = NULL;
7796     PetscLayout            nmap = NULL;
7797 
7798     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7799     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7800     PetscCall(PetscLayoutDestroy(&mat->cmap));
7801     mat->cmap          = nmap;
7802     mat->cmap->mapping = l2g;
7803   }
7804   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7805   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7806   PetscFunctionReturn(PETSC_SUCCESS);
7807 }
7808 
7809 /*@
7810   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7811 
7812   Logically Collective
7813 
7814   Input Parameters:
7815 + mat     - the matrix
7816 . fromRow - matrix from which to copy row block size
7817 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7818 
7819   Level: developer
7820 
7821 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7822 @*/
7823 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7824 {
7825   PetscFunctionBegin;
7826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7827   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7828   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7829   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7830   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7831   PetscFunctionReturn(PETSC_SUCCESS);
7832 }
7833 
7834 /*@
7835   MatResidual - Default routine to calculate the residual r = b - Ax
7836 
7837   Collective
7838 
7839   Input Parameters:
7840 + mat - the matrix
7841 . b   - the right-hand-side
7842 - x   - the approximate solution
7843 
7844   Output Parameter:
7845 . r - location to store the residual
7846 
7847   Level: developer
7848 
7849 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7850 @*/
7851 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7852 {
7853   PetscFunctionBegin;
7854   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7855   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7856   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7857   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7858   PetscValidType(mat, 1);
7859   MatCheckPreallocated(mat, 1);
7860   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7861   if (!mat->ops->residual) {
7862     PetscCall(MatMult(mat, x, r));
7863     PetscCall(VecAYPX(r, -1.0, b));
7864   } else {
7865     PetscUseTypeMethod(mat, residual, b, x, r);
7866   }
7867   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7868   PetscFunctionReturn(PETSC_SUCCESS);
7869 }
7870 
7871 /*MC
7872     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7873 
7874     Synopsis:
7875     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7876 
7877     Not Collective
7878 
7879     Input Parameters:
7880 +   A - the matrix
7881 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7882 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7883 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7884                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7885                  always used.
7886 
7887     Output Parameters:
7888 +   n - number of local rows in the (possibly compressed) matrix
7889 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7890 .   ja - the column indices
7891 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7892            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7893 
7894     Level: developer
7895 
7896     Note:
7897     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7898 
7899 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7900 M*/
7901 
7902 /*MC
7903     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7904 
7905     Synopsis:
7906     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7907 
7908     Not Collective
7909 
7910     Input Parameters:
7911 +   A - the  matrix
7912 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7913 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7914     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7915                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7916                  always used.
7917 .   n - number of local rows in the (possibly compressed) matrix
7918 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7919 .   ja - the column indices
7920 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7921            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7922 
7923     Level: developer
7924 
7925 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7926 M*/
7927 
7928 /*@C
7929   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7930 
7931   Collective
7932 
7933   Input Parameters:
7934 + mat             - the matrix
7935 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7936 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7937 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7938                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7939                  always used.
7940 
7941   Output Parameters:
7942 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7943 . 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
7944 . ja   - the column indices, use `NULL` if not needed
7945 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7946            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7947 
7948   Level: developer
7949 
7950   Notes:
7951   You CANNOT change any of the ia[] or ja[] values.
7952 
7953   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7954 
7955   Fortran Notes:
7956   Use
7957 .vb
7958     PetscInt, pointer :: ia(:),ja(:)
7959     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7960     ! Access the ith and jth entries via ia(i) and ja(j)
7961 .ve
7962   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7963 
7964 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7965 @*/
7966 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7967 {
7968   PetscFunctionBegin;
7969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7970   PetscValidType(mat, 1);
7971   if (n) PetscValidIntPointer(n, 5);
7972   if (ia) PetscValidPointer(ia, 6);
7973   if (ja) PetscValidPointer(ja, 7);
7974   if (done) PetscValidBoolPointer(done, 8);
7975   MatCheckPreallocated(mat, 1);
7976   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7977   else {
7978     if (done) *done = PETSC_TRUE;
7979     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7980     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7981     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7982   }
7983   PetscFunctionReturn(PETSC_SUCCESS);
7984 }
7985 
7986 /*@C
7987   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7988 
7989   Collective
7990 
7991   Input Parameters:
7992 + mat             - the matrix
7993 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
7994 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7995                 symmetrized
7996 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7997                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7998                  always used.
7999 . n               - number of columns in the (possibly compressed) matrix
8000 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8001 - ja              - the row indices
8002 
8003   Output Parameter:
8004 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8005 
8006   Level: developer
8007 
8008 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8009 @*/
8010 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8011 {
8012   PetscFunctionBegin;
8013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8014   PetscValidType(mat, 1);
8015   PetscValidIntPointer(n, 5);
8016   if (ia) PetscValidPointer(ia, 6);
8017   if (ja) PetscValidPointer(ja, 7);
8018   PetscValidBoolPointer(done, 8);
8019   MatCheckPreallocated(mat, 1);
8020   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8021   else {
8022     *done = PETSC_TRUE;
8023     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8024   }
8025   PetscFunctionReturn(PETSC_SUCCESS);
8026 }
8027 
8028 /*@C
8029   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8030 
8031   Collective
8032 
8033   Input Parameters:
8034 + mat             - the matrix
8035 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8036 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8037 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8038                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8039                  always used.
8040 . n               - size of (possibly compressed) matrix
8041 . ia              - the row pointers
8042 - ja              - the column indices
8043 
8044   Output Parameter:
8045 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8046 
8047   Level: developer
8048 
8049   Note:
8050   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8051   us of the array after it has been restored. If you pass `NULL`, it will
8052   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8053 
8054   Fortran Notes:
8055   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8056 
8057 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8058 @*/
8059 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8060 {
8061   PetscFunctionBegin;
8062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8063   PetscValidType(mat, 1);
8064   if (ia) PetscValidPointer(ia, 6);
8065   if (ja) PetscValidPointer(ja, 7);
8066   if (done) PetscValidBoolPointer(done, 8);
8067   MatCheckPreallocated(mat, 1);
8068 
8069   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8070   else {
8071     if (done) *done = PETSC_TRUE;
8072     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8073     if (n) *n = 0;
8074     if (ia) *ia = NULL;
8075     if (ja) *ja = NULL;
8076   }
8077   PetscFunctionReturn(PETSC_SUCCESS);
8078 }
8079 
8080 /*@C
8081   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8082 
8083   Collective
8084 
8085   Input Parameters:
8086 + mat             - the matrix
8087 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8088 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8089 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8090                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8091                  always used.
8092 
8093   Output Parameters:
8094 + n    - size of (possibly compressed) matrix
8095 . ia   - the column pointers
8096 . ja   - the row indices
8097 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8098 
8099   Level: developer
8100 
8101 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8102 @*/
8103 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8104 {
8105   PetscFunctionBegin;
8106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8107   PetscValidType(mat, 1);
8108   if (ia) PetscValidPointer(ia, 6);
8109   if (ja) PetscValidPointer(ja, 7);
8110   PetscValidBoolPointer(done, 8);
8111   MatCheckPreallocated(mat, 1);
8112 
8113   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8114   else {
8115     *done = PETSC_TRUE;
8116     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8117     if (n) *n = 0;
8118     if (ia) *ia = NULL;
8119     if (ja) *ja = NULL;
8120   }
8121   PetscFunctionReturn(PETSC_SUCCESS);
8122 }
8123 
8124 /*@C
8125   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8126   `MatGetColumnIJ()`.
8127 
8128   Collective
8129 
8130   Input Parameters:
8131 + mat        - the matrix
8132 . ncolors    - maximum color value
8133 . n          - number of entries in colorarray
8134 - colorarray - array indicating color for each column
8135 
8136   Output Parameter:
8137 . iscoloring - coloring generated using colorarray information
8138 
8139   Level: developer
8140 
8141 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8142 @*/
8143 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8144 {
8145   PetscFunctionBegin;
8146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8147   PetscValidType(mat, 1);
8148   PetscValidIntPointer(colorarray, 4);
8149   PetscValidPointer(iscoloring, 5);
8150   MatCheckPreallocated(mat, 1);
8151 
8152   if (!mat->ops->coloringpatch) {
8153     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8154   } else {
8155     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8156   }
8157   PetscFunctionReturn(PETSC_SUCCESS);
8158 }
8159 
8160 /*@
8161   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8162 
8163   Logically Collective
8164 
8165   Input Parameter:
8166 . mat - the factored matrix to be reset
8167 
8168   Level: developer
8169 
8170   Notes:
8171   This routine should be used only with factored matrices formed by in-place
8172   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8173   format).  This option can save memory, for example, when solving nonlinear
8174   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8175   ILU(0) preconditioner.
8176 
8177   One can specify in-place ILU(0) factorization by calling
8178 .vb
8179      PCType(pc,PCILU);
8180      PCFactorSeUseInPlace(pc);
8181 .ve
8182   or by using the options -pc_type ilu -pc_factor_in_place
8183 
8184   In-place factorization ILU(0) can also be used as a local
8185   solver for the blocks within the block Jacobi or additive Schwarz
8186   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8187   for details on setting local solver options.
8188 
8189   Most users should employ the `KSP` interface for linear solvers
8190   instead of working directly with matrix algebra routines such as this.
8191   See, e.g., `KSPCreate()`.
8192 
8193 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8194 @*/
8195 PetscErrorCode MatSetUnfactored(Mat mat)
8196 {
8197   PetscFunctionBegin;
8198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8199   PetscValidType(mat, 1);
8200   MatCheckPreallocated(mat, 1);
8201   mat->factortype = MAT_FACTOR_NONE;
8202   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8203   PetscUseTypeMethod(mat, setunfactored);
8204   PetscFunctionReturn(PETSC_SUCCESS);
8205 }
8206 
8207 /*MC
8208     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8209 
8210     Synopsis:
8211     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8212 
8213     Not Collective
8214 
8215     Input Parameter:
8216 .   x - matrix
8217 
8218     Output Parameters:
8219 +   xx_v - the Fortran pointer to the array
8220 -   ierr - error code
8221 
8222     Example of Usage:
8223 .vb
8224       PetscScalar, pointer xx_v(:,:)
8225       ....
8226       call MatDenseGetArrayF90(x,xx_v,ierr)
8227       a = xx_v(3)
8228       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8229 .ve
8230 
8231     Level: advanced
8232 
8233 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8234 M*/
8235 
8236 /*MC
8237     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8238     accessed with `MatDenseGetArrayF90()`.
8239 
8240     Synopsis:
8241     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8242 
8243     Not Collective
8244 
8245     Input Parameters:
8246 +   x - matrix
8247 -   xx_v - the Fortran90 pointer to the array
8248 
8249     Output Parameter:
8250 .   ierr - error code
8251 
8252     Example of Usage:
8253 .vb
8254        PetscScalar, pointer xx_v(:,:)
8255        ....
8256        call MatDenseGetArrayF90(x,xx_v,ierr)
8257        a = xx_v(3)
8258        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8259 .ve
8260 
8261     Level: advanced
8262 
8263 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8264 M*/
8265 
8266 /*MC
8267     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8268 
8269     Synopsis:
8270     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8271 
8272     Not Collective
8273 
8274     Input Parameter:
8275 .   x - matrix
8276 
8277     Output Parameters:
8278 +   xx_v - the Fortran pointer to the array
8279 -   ierr - error code
8280 
8281     Example of Usage:
8282 .vb
8283       PetscScalar, pointer xx_v(:)
8284       ....
8285       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8286       a = xx_v(3)
8287       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8288 .ve
8289 
8290     Level: advanced
8291 
8292 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8293 M*/
8294 
8295 /*MC
8296     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8297     accessed with `MatSeqAIJGetArrayF90()`.
8298 
8299     Synopsis:
8300     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8301 
8302     Not Collective
8303 
8304     Input Parameters:
8305 +   x - matrix
8306 -   xx_v - the Fortran90 pointer to the array
8307 
8308     Output Parameter:
8309 .   ierr - error code
8310 
8311     Example of Usage:
8312 .vb
8313        PetscScalar, pointer xx_v(:)
8314        ....
8315        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8316        a = xx_v(3)
8317        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8318 .ve
8319 
8320     Level: advanced
8321 
8322 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8323 M*/
8324 
8325 /*@
8326   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8327   as the original matrix.
8328 
8329   Collective
8330 
8331   Input Parameters:
8332 + mat   - the original matrix
8333 . isrow - parallel `IS` containing the rows this processor should obtain
8334 . 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.
8335 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8336 
8337   Output Parameter:
8338 . newmat - the new submatrix, of the same type as the original matrix
8339 
8340   Level: advanced
8341 
8342   Notes:
8343   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8344 
8345   Some matrix types place restrictions on the row and column indices, such
8346   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;
8347   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8348 
8349   The index sets may not have duplicate entries.
8350 
8351   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8352   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8353   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8354   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8355   you are finished using it.
8356 
8357   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8358   the input matrix.
8359 
8360   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8361 
8362   Example usage:
8363   Consider the following 8x8 matrix with 34 non-zero values, that is
8364   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8365   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8366   as follows
8367 .vb
8368             1  2  0  |  0  3  0  |  0  4
8369     Proc0   0  5  6  |  7  0  0  |  8  0
8370             9  0 10  | 11  0  0  | 12  0
8371     -------------------------------------
8372            13  0 14  | 15 16 17  |  0  0
8373     Proc1   0 18  0  | 19 20 21  |  0  0
8374             0  0  0  | 22 23  0  | 24  0
8375     -------------------------------------
8376     Proc2  25 26 27  |  0  0 28  | 29  0
8377            30  0  0  | 31 32 33  |  0 34
8378 .ve
8379 
8380   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8381 
8382 .vb
8383             2  0  |  0  3  0  |  0
8384     Proc0   5  6  |  7  0  0  |  8
8385     -------------------------------
8386     Proc1  18  0  | 19 20 21  |  0
8387     -------------------------------
8388     Proc2  26 27  |  0  0 28  | 29
8389             0  0  | 31 32 33  |  0
8390 .ve
8391 
8392 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8393 @*/
8394 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8395 {
8396   PetscMPIInt size;
8397   Mat        *local;
8398   IS          iscoltmp;
8399   PetscBool   flg;
8400 
8401   PetscFunctionBegin;
8402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8403   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8404   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8405   PetscValidPointer(newmat, 5);
8406   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8407   PetscValidType(mat, 1);
8408   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8409   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8410 
8411   MatCheckPreallocated(mat, 1);
8412   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8413 
8414   if (!iscol || isrow == iscol) {
8415     PetscBool   stride;
8416     PetscMPIInt grabentirematrix = 0, grab;
8417     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8418     if (stride) {
8419       PetscInt first, step, n, rstart, rend;
8420       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8421       if (step == 1) {
8422         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8423         if (rstart == first) {
8424           PetscCall(ISGetLocalSize(isrow, &n));
8425           if (n == rend - rstart) grabentirematrix = 1;
8426         }
8427       }
8428     }
8429     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8430     if (grab) {
8431       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8432       if (cll == MAT_INITIAL_MATRIX) {
8433         *newmat = mat;
8434         PetscCall(PetscObjectReference((PetscObject)mat));
8435       }
8436       PetscFunctionReturn(PETSC_SUCCESS);
8437     }
8438   }
8439 
8440   if (!iscol) {
8441     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8442   } else {
8443     iscoltmp = iscol;
8444   }
8445 
8446   /* if original matrix is on just one processor then use submatrix generated */
8447   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8448     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8449     goto setproperties;
8450   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8451     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8452     *newmat = *local;
8453     PetscCall(PetscFree(local));
8454     goto setproperties;
8455   } else if (!mat->ops->createsubmatrix) {
8456     /* Create a new matrix type that implements the operation using the full matrix */
8457     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8458     switch (cll) {
8459     case MAT_INITIAL_MATRIX:
8460       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8461       break;
8462     case MAT_REUSE_MATRIX:
8463       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8464       break;
8465     default:
8466       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8467     }
8468     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8469     goto setproperties;
8470   }
8471 
8472   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8473   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8474   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8475 
8476 setproperties:
8477   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8478   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8479   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8480   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8481   PetscFunctionReturn(PETSC_SUCCESS);
8482 }
8483 
8484 /*@
8485   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8486 
8487   Not Collective
8488 
8489   Input Parameters:
8490 + A - the matrix we wish to propagate options from
8491 - B - the matrix we wish to propagate options to
8492 
8493   Level: beginner
8494 
8495   Note:
8496   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8497 
8498 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8499 @*/
8500 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8501 {
8502   PetscFunctionBegin;
8503   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8504   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8505   B->symmetry_eternal            = A->symmetry_eternal;
8506   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8507   B->symmetric                   = A->symmetric;
8508   B->structurally_symmetric      = A->structurally_symmetric;
8509   B->spd                         = A->spd;
8510   B->hermitian                   = A->hermitian;
8511   PetscFunctionReturn(PETSC_SUCCESS);
8512 }
8513 
8514 /*@
8515   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8516   used during the assembly process to store values that belong to
8517   other processors.
8518 
8519   Not Collective
8520 
8521   Input Parameters:
8522 + mat   - the matrix
8523 . size  - the initial size of the stash.
8524 - bsize - the initial size of the block-stash(if used).
8525 
8526   Options Database Keys:
8527 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8528 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8529 
8530   Level: intermediate
8531 
8532   Notes:
8533   The block-stash is used for values set with `MatSetValuesBlocked()` while
8534   the stash is used for values set with `MatSetValues()`
8535 
8536   Run with the option -info and look for output of the form
8537   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8538   to determine the appropriate value, MM, to use for size and
8539   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8540   to determine the value, BMM to use for bsize
8541 
8542 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8543 @*/
8544 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8545 {
8546   PetscFunctionBegin;
8547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8548   PetscValidType(mat, 1);
8549   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8550   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8551   PetscFunctionReturn(PETSC_SUCCESS);
8552 }
8553 
8554 /*@
8555   MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8556   the matrix
8557 
8558   Neighbor-wise Collective
8559 
8560   Input Parameters:
8561 + A - the matrix
8562 . x - the vector to be multiplied by the interpolation operator
8563 - y - the vector to be added to the result
8564 
8565   Output Parameter:
8566 . w - the resulting vector
8567 
8568   Level: intermediate
8569 
8570   Notes:
8571   `w` may be the same vector as `y`.
8572 
8573   This allows one to use either the restriction or interpolation (its transpose)
8574   matrix to do the interpolation
8575 
8576 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8577 @*/
8578 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8579 {
8580   PetscInt M, N, Ny;
8581 
8582   PetscFunctionBegin;
8583   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8584   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8585   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8586   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8587   PetscCall(MatGetSize(A, &M, &N));
8588   PetscCall(VecGetSize(y, &Ny));
8589   if (M == Ny) {
8590     PetscCall(MatMultAdd(A, x, y, w));
8591   } else {
8592     PetscCall(MatMultTransposeAdd(A, x, y, w));
8593   }
8594   PetscFunctionReturn(PETSC_SUCCESS);
8595 }
8596 
8597 /*@
8598   MatInterpolate - y = A*x or A'*x depending on the shape of
8599   the matrix
8600 
8601   Neighbor-wise Collective
8602 
8603   Input Parameters:
8604 + A - the matrix
8605 - x - the vector to be interpolated
8606 
8607   Output Parameter:
8608 . y - the resulting vector
8609 
8610   Level: intermediate
8611 
8612   Note:
8613   This allows one to use either the restriction or interpolation (its transpose)
8614   matrix to do the interpolation
8615 
8616 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8617 @*/
8618 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8619 {
8620   PetscInt M, N, Ny;
8621 
8622   PetscFunctionBegin;
8623   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8624   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8625   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8626   PetscCall(MatGetSize(A, &M, &N));
8627   PetscCall(VecGetSize(y, &Ny));
8628   if (M == Ny) {
8629     PetscCall(MatMult(A, x, y));
8630   } else {
8631     PetscCall(MatMultTranspose(A, x, y));
8632   }
8633   PetscFunctionReturn(PETSC_SUCCESS);
8634 }
8635 
8636 /*@
8637   MatRestrict - y = A*x or A'*x
8638 
8639   Neighbor-wise Collective
8640 
8641   Input Parameters:
8642 + A - the matrix
8643 - x - the vector to be restricted
8644 
8645   Output Parameter:
8646 . y - the resulting vector
8647 
8648   Level: intermediate
8649 
8650   Note:
8651   This allows one to use either the restriction or interpolation (its transpose)
8652   matrix to do the restriction
8653 
8654 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8655 @*/
8656 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8657 {
8658   PetscInt M, N, Ny;
8659 
8660   PetscFunctionBegin;
8661   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8662   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8663   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8664   PetscCall(MatGetSize(A, &M, &N));
8665   PetscCall(VecGetSize(y, &Ny));
8666   if (M == Ny) {
8667     PetscCall(MatMult(A, x, y));
8668   } else {
8669     PetscCall(MatMultTranspose(A, x, y));
8670   }
8671   PetscFunctionReturn(PETSC_SUCCESS);
8672 }
8673 
8674 /*@
8675   MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8676 
8677   Neighbor-wise Collective
8678 
8679   Input Parameters:
8680 + A - the matrix
8681 . x - the input dense matrix to be multiplied
8682 - w - the input dense matrix to be added to the result
8683 
8684   Output Parameter:
8685 . y - the output dense matrix
8686 
8687   Level: intermediate
8688 
8689   Note:
8690   This allows one to use either the restriction or interpolation (its transpose)
8691   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8692   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8693 
8694 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8695 @*/
8696 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8697 {
8698   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8699   PetscBool trans = PETSC_TRUE;
8700   MatReuse  reuse = MAT_INITIAL_MATRIX;
8701 
8702   PetscFunctionBegin;
8703   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8704   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8705   PetscValidType(x, 2);
8706   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8707   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8708   PetscCall(MatGetSize(A, &M, &N));
8709   PetscCall(MatGetSize(x, &Mx, &Nx));
8710   if (N == Mx) trans = PETSC_FALSE;
8711   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);
8712   Mo = trans ? N : M;
8713   if (*y) {
8714     PetscCall(MatGetSize(*y, &My, &Ny));
8715     if (Mo == My && Nx == Ny) {
8716       reuse = MAT_REUSE_MATRIX;
8717     } else {
8718       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);
8719       PetscCall(MatDestroy(y));
8720     }
8721   }
8722 
8723   if (w && *y == w) { /* this is to minimize changes in PCMG */
8724     PetscBool flg;
8725 
8726     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8727     if (w) {
8728       PetscInt My, Ny, Mw, Nw;
8729 
8730       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8731       PetscCall(MatGetSize(*y, &My, &Ny));
8732       PetscCall(MatGetSize(w, &Mw, &Nw));
8733       if (!flg || My != Mw || Ny != Nw) w = NULL;
8734     }
8735     if (!w) {
8736       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8737       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8738       PetscCall(PetscObjectDereference((PetscObject)w));
8739     } else {
8740       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8741     }
8742   }
8743   if (!trans) {
8744     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8745   } else {
8746     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8747   }
8748   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8749   PetscFunctionReturn(PETSC_SUCCESS);
8750 }
8751 
8752 /*@
8753   MatMatInterpolate - Y = A*X or A'*X
8754 
8755   Neighbor-wise Collective
8756 
8757   Input Parameters:
8758 + A - the matrix
8759 - x - the input dense matrix
8760 
8761   Output Parameter:
8762 . y - the output dense matrix
8763 
8764   Level: intermediate
8765 
8766   Note:
8767   This allows one to use either the restriction or interpolation (its transpose)
8768   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8769   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8770 
8771 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8772 @*/
8773 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8774 {
8775   PetscFunctionBegin;
8776   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8777   PetscFunctionReturn(PETSC_SUCCESS);
8778 }
8779 
8780 /*@
8781   MatMatRestrict - Y = A*X or A'*X
8782 
8783   Neighbor-wise Collective
8784 
8785   Input Parameters:
8786 + A - the matrix
8787 - x - the input dense matrix
8788 
8789   Output Parameter:
8790 . y - the output dense matrix
8791 
8792   Level: intermediate
8793 
8794   Note:
8795   This allows one to use either the restriction or interpolation (its transpose)
8796   matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8797   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8798 
8799 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8800 @*/
8801 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8802 {
8803   PetscFunctionBegin;
8804   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8805   PetscFunctionReturn(PETSC_SUCCESS);
8806 }
8807 
8808 /*@
8809   MatGetNullSpace - retrieves the null space of a matrix.
8810 
8811   Logically Collective
8812 
8813   Input Parameters:
8814 + mat    - the matrix
8815 - nullsp - the null space object
8816 
8817   Level: developer
8818 
8819 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8820 @*/
8821 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8822 {
8823   PetscFunctionBegin;
8824   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8825   PetscValidPointer(nullsp, 2);
8826   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8827   PetscFunctionReturn(PETSC_SUCCESS);
8828 }
8829 
8830 /*@
8831   MatSetNullSpace - attaches a null space to a matrix.
8832 
8833   Logically Collective
8834 
8835   Input Parameters:
8836 + mat    - the matrix
8837 - nullsp - the null space object
8838 
8839   Level: advanced
8840 
8841   Notes:
8842   This null space is used by the `KSP` linear solvers to solve singular systems.
8843 
8844   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`
8845 
8846   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
8847   to zero but the linear system will still be solved in a least squares sense.
8848 
8849   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8850   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).
8851   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
8852   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
8853   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).
8854   This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8855 
8856   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8857   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8858   routine also automatically calls `MatSetTransposeNullSpace()`.
8859 
8860   The user should call `MatNullSpaceDestroy()`.
8861 
8862 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8863           `KSPSetPCSide()`
8864 @*/
8865 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8866 {
8867   PetscFunctionBegin;
8868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8869   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8870   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8871   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8872   mat->nullsp = nullsp;
8873   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8874   PetscFunctionReturn(PETSC_SUCCESS);
8875 }
8876 
8877 /*@
8878   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8879 
8880   Logically Collective
8881 
8882   Input Parameters:
8883 + mat    - the matrix
8884 - nullsp - the null space object
8885 
8886   Level: developer
8887 
8888 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8889 @*/
8890 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8891 {
8892   PetscFunctionBegin;
8893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8894   PetscValidType(mat, 1);
8895   PetscValidPointer(nullsp, 2);
8896   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8897   PetscFunctionReturn(PETSC_SUCCESS);
8898 }
8899 
8900 /*@
8901   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8902 
8903   Logically Collective
8904 
8905   Input Parameters:
8906 + mat    - the matrix
8907 - nullsp - the null space object
8908 
8909   Level: advanced
8910 
8911   Notes:
8912   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8913 
8914   See `MatSetNullSpace()`
8915 
8916 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8917 @*/
8918 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8919 {
8920   PetscFunctionBegin;
8921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8922   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8923   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8924   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8925   mat->transnullsp = nullsp;
8926   PetscFunctionReturn(PETSC_SUCCESS);
8927 }
8928 
8929 /*@
8930   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8931   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8932 
8933   Logically Collective
8934 
8935   Input Parameters:
8936 + mat    - the matrix
8937 - nullsp - the null space object
8938 
8939   Level: advanced
8940 
8941   Notes:
8942   Overwrites any previous near null space that may have been attached
8943 
8944   You can remove the null space by calling this routine with an nullsp of `NULL`
8945 
8946 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8947 @*/
8948 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8949 {
8950   PetscFunctionBegin;
8951   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8952   PetscValidType(mat, 1);
8953   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8954   MatCheckPreallocated(mat, 1);
8955   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8956   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8957   mat->nearnullsp = nullsp;
8958   PetscFunctionReturn(PETSC_SUCCESS);
8959 }
8960 
8961 /*@
8962   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8963 
8964   Not Collective
8965 
8966   Input Parameter:
8967 . mat - the matrix
8968 
8969   Output Parameter:
8970 . nullsp - the null space object, `NULL` if not set
8971 
8972   Level: advanced
8973 
8974 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8975 @*/
8976 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8977 {
8978   PetscFunctionBegin;
8979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8980   PetscValidType(mat, 1);
8981   PetscValidPointer(nullsp, 2);
8982   MatCheckPreallocated(mat, 1);
8983   *nullsp = mat->nearnullsp;
8984   PetscFunctionReturn(PETSC_SUCCESS);
8985 }
8986 
8987 /*@C
8988   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8989 
8990   Collective
8991 
8992   Input Parameters:
8993 + mat  - the matrix
8994 . row  - row/column permutation
8995 - info - information on desired factorization process
8996 
8997   Level: developer
8998 
8999   Notes:
9000   Probably really in-place only when level of fill is zero, otherwise allocates
9001   new space to store factored matrix and deletes previous memory.
9002 
9003   Most users should employ the `KSP` interface for linear solvers
9004   instead of working directly with matrix algebra routines such as this.
9005   See, e.g., `KSPCreate()`.
9006 
9007   Developer Notes:
9008   The Fortran interface is not autogenerated as the
9009   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9010 
9011 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9012 @*/
9013 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9014 {
9015   PetscFunctionBegin;
9016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9017   PetscValidType(mat, 1);
9018   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9019   PetscValidPointer(info, 3);
9020   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9021   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9022   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9023   MatCheckPreallocated(mat, 1);
9024   PetscUseTypeMethod(mat, iccfactor, row, info);
9025   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9026   PetscFunctionReturn(PETSC_SUCCESS);
9027 }
9028 
9029 /*@
9030   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9031   ghosted ones.
9032 
9033   Not Collective
9034 
9035   Input Parameters:
9036 + mat  - the matrix
9037 - diag - the diagonal values, including ghost ones
9038 
9039   Level: developer
9040 
9041   Notes:
9042   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9043 
9044   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9045 
9046 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9047 @*/
9048 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9049 {
9050   PetscMPIInt size;
9051 
9052   PetscFunctionBegin;
9053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9054   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9055   PetscValidType(mat, 1);
9056 
9057   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9058   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9059   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9060   if (size == 1) {
9061     PetscInt n, m;
9062     PetscCall(VecGetSize(diag, &n));
9063     PetscCall(MatGetSize(mat, NULL, &m));
9064     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9065     PetscCall(MatDiagonalScale(mat, NULL, diag));
9066   } else {
9067     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9068   }
9069   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9070   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9071   PetscFunctionReturn(PETSC_SUCCESS);
9072 }
9073 
9074 /*@
9075   MatGetInertia - Gets the inertia from a factored matrix
9076 
9077   Collective
9078 
9079   Input Parameter:
9080 . mat - the matrix
9081 
9082   Output Parameters:
9083 + nneg  - number of negative eigenvalues
9084 . nzero - number of zero eigenvalues
9085 - npos  - number of positive eigenvalues
9086 
9087   Level: advanced
9088 
9089   Note:
9090   Matrix must have been factored by `MatCholeskyFactor()`
9091 
9092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9093 @*/
9094 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9095 {
9096   PetscFunctionBegin;
9097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9098   PetscValidType(mat, 1);
9099   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9100   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9101   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9102   PetscFunctionReturn(PETSC_SUCCESS);
9103 }
9104 
9105 /*@C
9106   MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9107 
9108   Neighbor-wise Collective
9109 
9110   Input Parameters:
9111 + mat - the factored matrix obtained with `MatGetFactor()`
9112 - b   - the right-hand-side vectors
9113 
9114   Output Parameter:
9115 . x - the result vectors
9116 
9117   Level: developer
9118 
9119   Note:
9120   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9121   call `MatSolves`(A,x,x).
9122 
9123 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9124 @*/
9125 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9126 {
9127   PetscFunctionBegin;
9128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9129   PetscValidType(mat, 1);
9130   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9131   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9132   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9133 
9134   MatCheckPreallocated(mat, 1);
9135   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9136   PetscUseTypeMethod(mat, solves, b, x);
9137   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9138   PetscFunctionReturn(PETSC_SUCCESS);
9139 }
9140 
9141 /*@
9142   MatIsSymmetric - Test whether a matrix is symmetric
9143 
9144   Collective
9145 
9146   Input Parameters:
9147 + A   - the matrix to test
9148 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9149 
9150   Output Parameter:
9151 . flg - the result
9152 
9153   Level: intermediate
9154 
9155   Notes:
9156   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9157 
9158   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9159 
9160   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9161   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9162 
9163 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9164           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9165 @*/
9166 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9167 {
9168   PetscFunctionBegin;
9169   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9170   PetscValidBoolPointer(flg, 3);
9171 
9172   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9173   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9174   else {
9175     PetscUseTypeMethod(A, issymmetric, tol, flg);
9176     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9177   }
9178   PetscFunctionReturn(PETSC_SUCCESS);
9179 }
9180 
9181 /*@
9182   MatIsHermitian - Test whether a matrix is Hermitian
9183 
9184   Collective
9185 
9186   Input Parameters:
9187 + A   - the matrix to test
9188 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9189 
9190   Output Parameter:
9191 . flg - the result
9192 
9193   Level: intermediate
9194 
9195   Notes:
9196   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9197 
9198   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9199 
9200   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9201   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9202 
9203 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9204           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9205 @*/
9206 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9207 {
9208   PetscFunctionBegin;
9209   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9210   PetscValidBoolPointer(flg, 3);
9211 
9212   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9213   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9214   else {
9215     PetscUseTypeMethod(A, ishermitian, tol, flg);
9216     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9217   }
9218   PetscFunctionReturn(PETSC_SUCCESS);
9219 }
9220 
9221 /*@
9222   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9223 
9224   Not Collective
9225 
9226   Input Parameter:
9227 . A - the matrix to check
9228 
9229   Output Parameters:
9230 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9231 - flg - the result (only valid if set is `PETSC_TRUE`)
9232 
9233   Level: advanced
9234 
9235   Notes:
9236   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9237   if you want it explicitly checked
9238 
9239   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9240   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9241 
9242 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9243 @*/
9244 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9245 {
9246   PetscFunctionBegin;
9247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9248   PetscValidBoolPointer(set, 2);
9249   PetscValidBoolPointer(flg, 3);
9250   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9251     *set = PETSC_TRUE;
9252     *flg = PetscBool3ToBool(A->symmetric);
9253   } else {
9254     *set = PETSC_FALSE;
9255   }
9256   PetscFunctionReturn(PETSC_SUCCESS);
9257 }
9258 
9259 /*@
9260   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9261 
9262   Not Collective
9263 
9264   Input Parameter:
9265 . A - the matrix to check
9266 
9267   Output Parameters:
9268 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9269 - flg - the result (only valid if set is `PETSC_TRUE`)
9270 
9271   Level: advanced
9272 
9273   Notes:
9274   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9275 
9276   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9277   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9278 
9279 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9280 @*/
9281 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9282 {
9283   PetscFunctionBegin;
9284   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9285   PetscValidBoolPointer(set, 2);
9286   PetscValidBoolPointer(flg, 3);
9287   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9288     *set = PETSC_TRUE;
9289     *flg = PetscBool3ToBool(A->spd);
9290   } else {
9291     *set = PETSC_FALSE;
9292   }
9293   PetscFunctionReturn(PETSC_SUCCESS);
9294 }
9295 
9296 /*@
9297   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9298 
9299   Not Collective
9300 
9301   Input Parameter:
9302 . A - the matrix to check
9303 
9304   Output Parameters:
9305 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9306 - flg - the result (only valid if set is `PETSC_TRUE`)
9307 
9308   Level: advanced
9309 
9310   Notes:
9311   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9312   if you want it explicitly checked
9313 
9314   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9315   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9316 
9317 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9318 @*/
9319 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9320 {
9321   PetscFunctionBegin;
9322   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9323   PetscValidBoolPointer(set, 2);
9324   PetscValidBoolPointer(flg, 3);
9325   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9326     *set = PETSC_TRUE;
9327     *flg = PetscBool3ToBool(A->hermitian);
9328   } else {
9329     *set = PETSC_FALSE;
9330   }
9331   PetscFunctionReturn(PETSC_SUCCESS);
9332 }
9333 
9334 /*@
9335   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9336 
9337   Collective
9338 
9339   Input Parameter:
9340 . A - the matrix to test
9341 
9342   Output Parameter:
9343 . flg - the result
9344 
9345   Level: intermediate
9346 
9347   Notes:
9348   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9349 
9350   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
9351   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9352 
9353 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9354 @*/
9355 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9356 {
9357   PetscFunctionBegin;
9358   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9359   PetscValidBoolPointer(flg, 2);
9360   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9361     *flg = PetscBool3ToBool(A->structurally_symmetric);
9362   } else {
9363     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9364     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9365   }
9366   PetscFunctionReturn(PETSC_SUCCESS);
9367 }
9368 
9369 /*@
9370   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9371 
9372   Not Collective
9373 
9374   Input Parameter:
9375 . A - the matrix to check
9376 
9377   Output Parameters:
9378 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9379 - flg - the result (only valid if set is PETSC_TRUE)
9380 
9381   Level: advanced
9382 
9383   Notes:
9384   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
9385   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9386 
9387   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9388 
9389 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9390 @*/
9391 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9392 {
9393   PetscFunctionBegin;
9394   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9395   PetscValidBoolPointer(set, 2);
9396   PetscValidBoolPointer(flg, 3);
9397   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9398     *set = PETSC_TRUE;
9399     *flg = PetscBool3ToBool(A->structurally_symmetric);
9400   } else {
9401     *set = PETSC_FALSE;
9402   }
9403   PetscFunctionReturn(PETSC_SUCCESS);
9404 }
9405 
9406 /*@
9407   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9408   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9409 
9410   Not Collective
9411 
9412   Input Parameter:
9413 . mat - the matrix
9414 
9415   Output Parameters:
9416 + nstash    - the size of the stash
9417 . reallocs  - the number of additional mallocs incurred.
9418 . bnstash   - the size of the block stash
9419 - breallocs - the number of additional mallocs incurred.in the block stash
9420 
9421   Level: advanced
9422 
9423 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9424 @*/
9425 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9426 {
9427   PetscFunctionBegin;
9428   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9429   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9430   PetscFunctionReturn(PETSC_SUCCESS);
9431 }
9432 
9433 /*@C
9434   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9435   parallel layout, `PetscLayout` for rows and columns
9436 
9437   Collective
9438 
9439   Input Parameter:
9440 . mat - the matrix
9441 
9442   Output Parameters:
9443 + right - (optional) vector that the matrix can be multiplied against
9444 - left  - (optional) vector that the matrix vector product can be stored in
9445 
9446   Level: advanced
9447 
9448   Notes:
9449   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()`.
9450 
9451   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9452 
9453 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9454 @*/
9455 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9456 {
9457   PetscFunctionBegin;
9458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9459   PetscValidType(mat, 1);
9460   if (mat->ops->getvecs) {
9461     PetscUseTypeMethod(mat, getvecs, right, left);
9462   } else {
9463     if (right) {
9464       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9465       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9466       PetscCall(VecSetType(*right, mat->defaultvectype));
9467 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9468       if (mat->boundtocpu && mat->bindingpropagates) {
9469         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9470         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9471       }
9472 #endif
9473     }
9474     if (left) {
9475       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9476       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9477       PetscCall(VecSetType(*left, mat->defaultvectype));
9478 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9479       if (mat->boundtocpu && mat->bindingpropagates) {
9480         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9481         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9482       }
9483 #endif
9484     }
9485   }
9486   PetscFunctionReturn(PETSC_SUCCESS);
9487 }
9488 
9489 /*@C
9490   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9491   with default values.
9492 
9493   Not Collective
9494 
9495   Input Parameter:
9496 . info - the `MatFactorInfo` data structure
9497 
9498   Level: developer
9499 
9500   Notes:
9501   The solvers are generally used through the `KSP` and `PC` objects, for example
9502   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9503 
9504   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9505 
9506   Developer Notes:
9507   The Fortran interface is not autogenerated as the
9508   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9509 
9510 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9511 @*/
9512 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9513 {
9514   PetscFunctionBegin;
9515   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9516   PetscFunctionReturn(PETSC_SUCCESS);
9517 }
9518 
9519 /*@
9520   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9521 
9522   Collective
9523 
9524   Input Parameters:
9525 + mat - the factored matrix
9526 - is  - the index set defining the Schur indices (0-based)
9527 
9528   Level: advanced
9529 
9530   Notes:
9531   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9532 
9533   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9534 
9535   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9536 
9537 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9538           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9539 @*/
9540 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9541 {
9542   PetscErrorCode (*f)(Mat, IS);
9543 
9544   PetscFunctionBegin;
9545   PetscValidType(mat, 1);
9546   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9547   PetscValidType(is, 2);
9548   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9549   PetscCheckSameComm(mat, 1, is, 2);
9550   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9551   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9552   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9553   PetscCall(MatDestroy(&mat->schur));
9554   PetscCall((*f)(mat, is));
9555   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9556   PetscFunctionReturn(PETSC_SUCCESS);
9557 }
9558 
9559 /*@
9560   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9561 
9562   Logically Collective
9563 
9564   Input Parameters:
9565 + F      - the factored matrix obtained by calling `MatGetFactor()`
9566 . S      - location where to return the Schur complement, can be `NULL`
9567 - status - the status of the Schur complement matrix, can be `NULL`
9568 
9569   Level: advanced
9570 
9571   Notes:
9572   You must call `MatFactorSetSchurIS()` before calling this routine.
9573 
9574   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9575 
9576   The routine provides a copy of the Schur matrix stored within the solver data structures.
9577   The caller must destroy the object when it is no longer needed.
9578   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9579 
9580   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)
9581 
9582   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9583 
9584   Developer Notes:
9585   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9586   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9587 
9588 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9589 @*/
9590 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9591 {
9592   PetscFunctionBegin;
9593   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9594   if (S) PetscValidPointer(S, 2);
9595   if (status) PetscValidPointer(status, 3);
9596   if (S) {
9597     PetscErrorCode (*f)(Mat, Mat *);
9598 
9599     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9600     if (f) {
9601       PetscCall((*f)(F, S));
9602     } else {
9603       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9604     }
9605   }
9606   if (status) *status = F->schur_status;
9607   PetscFunctionReturn(PETSC_SUCCESS);
9608 }
9609 
9610 /*@
9611   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9612 
9613   Logically Collective
9614 
9615   Input Parameters:
9616 + F      - the factored matrix obtained by calling `MatGetFactor()`
9617 . S      - location where to return the Schur complement, can be `NULL`
9618 - status - the status of the Schur complement matrix, can be `NULL`
9619 
9620   Level: advanced
9621 
9622   Notes:
9623   You must call `MatFactorSetSchurIS()` before calling this routine.
9624 
9625   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9626 
9627   The routine returns a the Schur Complement stored within the data structures of the solver.
9628 
9629   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9630 
9631   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9632 
9633   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9634 
9635   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9636 
9637 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9638 @*/
9639 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9640 {
9641   PetscFunctionBegin;
9642   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9643   if (S) PetscValidPointer(S, 2);
9644   if (status) PetscValidPointer(status, 3);
9645   if (S) *S = F->schur;
9646   if (status) *status = F->schur_status;
9647   PetscFunctionReturn(PETSC_SUCCESS);
9648 }
9649 
9650 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9651 {
9652   Mat S = F->schur;
9653 
9654   PetscFunctionBegin;
9655   switch (F->schur_status) {
9656   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9657   case MAT_FACTOR_SCHUR_INVERTED:
9658     if (S) {
9659       S->ops->solve             = NULL;
9660       S->ops->matsolve          = NULL;
9661       S->ops->solvetranspose    = NULL;
9662       S->ops->matsolvetranspose = NULL;
9663       S->ops->solveadd          = NULL;
9664       S->ops->solvetransposeadd = NULL;
9665       S->factortype             = MAT_FACTOR_NONE;
9666       PetscCall(PetscFree(S->solvertype));
9667     }
9668   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9669     break;
9670   default:
9671     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9672   }
9673   PetscFunctionReturn(PETSC_SUCCESS);
9674 }
9675 
9676 /*@
9677   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9678 
9679   Logically Collective
9680 
9681   Input Parameters:
9682 + F      - the factored matrix obtained by calling `MatGetFactor()`
9683 . S      - location where the Schur complement is stored
9684 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9685 
9686   Level: advanced
9687 
9688 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9689 @*/
9690 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9691 {
9692   PetscFunctionBegin;
9693   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9694   if (S) {
9695     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9696     *S = NULL;
9697   }
9698   F->schur_status = status;
9699   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9700   PetscFunctionReturn(PETSC_SUCCESS);
9701 }
9702 
9703 /*@
9704   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9705 
9706   Logically Collective
9707 
9708   Input Parameters:
9709 + F   - the factored matrix obtained by calling `MatGetFactor()`
9710 . rhs - location where the right hand side of the Schur complement system is stored
9711 - sol - location where the solution of the Schur complement system has to be returned
9712 
9713   Level: advanced
9714 
9715   Notes:
9716   The sizes of the vectors should match the size of the Schur complement
9717 
9718   Must be called after `MatFactorSetSchurIS()`
9719 
9720 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9721 @*/
9722 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9723 {
9724   PetscFunctionBegin;
9725   PetscValidType(F, 1);
9726   PetscValidType(rhs, 2);
9727   PetscValidType(sol, 3);
9728   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9729   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9730   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9731   PetscCheckSameComm(F, 1, rhs, 2);
9732   PetscCheckSameComm(F, 1, sol, 3);
9733   PetscCall(MatFactorFactorizeSchurComplement(F));
9734   switch (F->schur_status) {
9735   case MAT_FACTOR_SCHUR_FACTORED:
9736     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9737     break;
9738   case MAT_FACTOR_SCHUR_INVERTED:
9739     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9740     break;
9741   default:
9742     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9743   }
9744   PetscFunctionReturn(PETSC_SUCCESS);
9745 }
9746 
9747 /*@
9748   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9749 
9750   Logically Collective
9751 
9752   Input Parameters:
9753 + F   - the factored matrix obtained by calling `MatGetFactor()`
9754 . rhs - location where the right hand side of the Schur complement system is stored
9755 - sol - location where the solution of the Schur complement system has to be returned
9756 
9757   Level: advanced
9758 
9759   Notes:
9760   The sizes of the vectors should match the size of the Schur complement
9761 
9762   Must be called after `MatFactorSetSchurIS()`
9763 
9764 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9765 @*/
9766 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9767 {
9768   PetscFunctionBegin;
9769   PetscValidType(F, 1);
9770   PetscValidType(rhs, 2);
9771   PetscValidType(sol, 3);
9772   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9773   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9774   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9775   PetscCheckSameComm(F, 1, rhs, 2);
9776   PetscCheckSameComm(F, 1, sol, 3);
9777   PetscCall(MatFactorFactorizeSchurComplement(F));
9778   switch (F->schur_status) {
9779   case MAT_FACTOR_SCHUR_FACTORED:
9780     PetscCall(MatSolve(F->schur, rhs, sol));
9781     break;
9782   case MAT_FACTOR_SCHUR_INVERTED:
9783     PetscCall(MatMult(F->schur, rhs, sol));
9784     break;
9785   default:
9786     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9787   }
9788   PetscFunctionReturn(PETSC_SUCCESS);
9789 }
9790 
9791 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9792 #if PetscDefined(HAVE_CUDA)
9793 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9794 #endif
9795 
9796 /* Schur status updated in the interface */
9797 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9798 {
9799   Mat S = F->schur;
9800 
9801   PetscFunctionBegin;
9802   if (S) {
9803     PetscMPIInt size;
9804     PetscBool   isdense, isdensecuda;
9805 
9806     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9807     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9808     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9809     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9810     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9811     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9812     if (isdense) {
9813       PetscCall(MatSeqDenseInvertFactors_Private(S));
9814     } else if (isdensecuda) {
9815 #if defined(PETSC_HAVE_CUDA)
9816       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9817 #endif
9818     }
9819     // HIP??????????????
9820     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9821   }
9822   PetscFunctionReturn(PETSC_SUCCESS);
9823 }
9824 
9825 /*@
9826   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9827 
9828   Logically Collective
9829 
9830   Input Parameter:
9831 . F - the factored matrix obtained by calling `MatGetFactor()`
9832 
9833   Level: advanced
9834 
9835   Notes:
9836   Must be called after `MatFactorSetSchurIS()`.
9837 
9838   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9839 
9840 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9841 @*/
9842 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9843 {
9844   PetscFunctionBegin;
9845   PetscValidType(F, 1);
9846   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9847   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9848   PetscCall(MatFactorFactorizeSchurComplement(F));
9849   PetscCall(MatFactorInvertSchurComplement_Private(F));
9850   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9851   PetscFunctionReturn(PETSC_SUCCESS);
9852 }
9853 
9854 /*@
9855   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9856 
9857   Logically Collective
9858 
9859   Input Parameter:
9860 . F - the factored matrix obtained by calling `MatGetFactor()`
9861 
9862   Level: advanced
9863 
9864   Note:
9865   Must be called after `MatFactorSetSchurIS()`
9866 
9867 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9868 @*/
9869 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9870 {
9871   MatFactorInfo info;
9872 
9873   PetscFunctionBegin;
9874   PetscValidType(F, 1);
9875   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9876   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9877   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9878   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9879   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9880     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9881   } else {
9882     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9883   }
9884   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9885   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9886   PetscFunctionReturn(PETSC_SUCCESS);
9887 }
9888 
9889 /*@
9890   MatPtAP - Creates the matrix product C = P^T * A * P
9891 
9892   Neighbor-wise Collective
9893 
9894   Input Parameters:
9895 + A     - the matrix
9896 . P     - the projection matrix
9897 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9898 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9899           if the result is a dense matrix this is irrelevant
9900 
9901   Output Parameter:
9902 . C - the product matrix
9903 
9904   Level: intermediate
9905 
9906   Notes:
9907   C will be created and must be destroyed by the user with `MatDestroy()`.
9908 
9909   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9910 
9911   Developer Notes:
9912   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9913 
9914 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9915 @*/
9916 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9917 {
9918   PetscFunctionBegin;
9919   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9920   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9921 
9922   if (scall == MAT_INITIAL_MATRIX) {
9923     PetscCall(MatProductCreate(A, P, NULL, C));
9924     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9925     PetscCall(MatProductSetAlgorithm(*C, "default"));
9926     PetscCall(MatProductSetFill(*C, fill));
9927 
9928     (*C)->product->api_user = PETSC_TRUE;
9929     PetscCall(MatProductSetFromOptions(*C));
9930     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);
9931     PetscCall(MatProductSymbolic(*C));
9932   } else { /* scall == MAT_REUSE_MATRIX */
9933     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9934   }
9935 
9936   PetscCall(MatProductNumeric(*C));
9937   (*C)->symmetric = A->symmetric;
9938   (*C)->spd       = A->spd;
9939   PetscFunctionReturn(PETSC_SUCCESS);
9940 }
9941 
9942 /*@
9943   MatRARt - Creates the matrix product C = R * A * R^T
9944 
9945   Neighbor-wise Collective
9946 
9947   Input Parameters:
9948 + A     - the matrix
9949 . R     - the projection matrix
9950 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9951 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9952           if the result is a dense matrix this is irrelevant
9953 
9954   Output Parameter:
9955 . C - the product matrix
9956 
9957   Level: intermediate
9958 
9959   Notes:
9960   C will be created and must be destroyed by the user with `MatDestroy()`.
9961 
9962   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9963 
9964   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9965   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9966   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9967   We recommend using MatPtAP().
9968 
9969 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9970 @*/
9971 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9972 {
9973   PetscFunctionBegin;
9974   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9975   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9976 
9977   if (scall == MAT_INITIAL_MATRIX) {
9978     PetscCall(MatProductCreate(A, R, NULL, C));
9979     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9980     PetscCall(MatProductSetAlgorithm(*C, "default"));
9981     PetscCall(MatProductSetFill(*C, fill));
9982 
9983     (*C)->product->api_user = PETSC_TRUE;
9984     PetscCall(MatProductSetFromOptions(*C));
9985     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);
9986     PetscCall(MatProductSymbolic(*C));
9987   } else { /* scall == MAT_REUSE_MATRIX */
9988     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9989   }
9990 
9991   PetscCall(MatProductNumeric(*C));
9992   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9993   PetscFunctionReturn(PETSC_SUCCESS);
9994 }
9995 
9996 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9997 {
9998   PetscFunctionBegin;
9999   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10000 
10001   if (scall == MAT_INITIAL_MATRIX) {
10002     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10003     PetscCall(MatProductCreate(A, B, NULL, C));
10004     PetscCall(MatProductSetType(*C, ptype));
10005     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10006     PetscCall(MatProductSetFill(*C, fill));
10007 
10008     (*C)->product->api_user = PETSC_TRUE;
10009     PetscCall(MatProductSetFromOptions(*C));
10010     PetscCall(MatProductSymbolic(*C));
10011   } else { /* scall == MAT_REUSE_MATRIX */
10012     Mat_Product *product = (*C)->product;
10013     PetscBool    isdense;
10014 
10015     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10016     if (isdense && product && product->type != ptype) {
10017       PetscCall(MatProductClear(*C));
10018       product = NULL;
10019     }
10020     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10021     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10022       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10023       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10024       product           = (*C)->product;
10025       product->fill     = fill;
10026       product->api_user = PETSC_TRUE;
10027       product->clear    = PETSC_TRUE;
10028 
10029       PetscCall(MatProductSetType(*C, ptype));
10030       PetscCall(MatProductSetFromOptions(*C));
10031       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);
10032       PetscCall(MatProductSymbolic(*C));
10033     } else { /* user may change input matrices A or B when REUSE */
10034       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10035     }
10036   }
10037   PetscCall(MatProductNumeric(*C));
10038   PetscFunctionReturn(PETSC_SUCCESS);
10039 }
10040 
10041 /*@
10042   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10043 
10044   Neighbor-wise Collective
10045 
10046   Input Parameters:
10047 + A     - the left matrix
10048 . B     - the right matrix
10049 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10050 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10051           if the result is a dense matrix this is irrelevant
10052 
10053   Output Parameter:
10054 . C - the product matrix
10055 
10056   Notes:
10057   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10058 
10059   `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
10060   call to this function with `MAT_INITIAL_MATRIX`.
10061 
10062   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10063 
10064   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`,
10065   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10066 
10067   Example of Usage:
10068 .vb
10069      MatProductCreate(A,B,NULL,&C);
10070      MatProductSetType(C,MATPRODUCT_AB);
10071      MatProductSymbolic(C);
10072      MatProductNumeric(C); // compute C=A * B
10073      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10074      MatProductNumeric(C);
10075      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10076      MatProductNumeric(C);
10077 .ve
10078 
10079   Level: intermediate
10080 
10081 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10082 @*/
10083 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10084 {
10085   PetscFunctionBegin;
10086   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10087   PetscFunctionReturn(PETSC_SUCCESS);
10088 }
10089 
10090 /*@
10091   MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10092 
10093   Neighbor-wise Collective
10094 
10095   Input Parameters:
10096 + A     - the left matrix
10097 . B     - the right matrix
10098 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10099 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10100 
10101   Output Parameter:
10102 . C - the product matrix
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   Options Database Keys:
10120 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10121               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10122               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10123 
10124 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10125 @*/
10126 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10127 {
10128   PetscFunctionBegin;
10129   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10130   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10131   PetscFunctionReturn(PETSC_SUCCESS);
10132 }
10133 
10134 /*@
10135   MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10136 
10137   Neighbor-wise Collective
10138 
10139   Input Parameters:
10140 + A     - the left matrix
10141 . B     - the right matrix
10142 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10143 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10144 
10145   Output Parameter:
10146 . C - the product matrix
10147 
10148   Level: intermediate
10149 
10150   Notes:
10151   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10152 
10153   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10154 
10155   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10156 
10157   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10158   actually needed.
10159 
10160   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10161   which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10162 
10163 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10164 @*/
10165 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10166 {
10167   PetscFunctionBegin;
10168   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10169   PetscFunctionReturn(PETSC_SUCCESS);
10170 }
10171 
10172 /*@
10173   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10174 
10175   Neighbor-wise Collective
10176 
10177   Input Parameters:
10178 + A     - the left matrix
10179 . B     - the middle matrix
10180 . C     - the right matrix
10181 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10182 - 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
10183           if the result is a dense matrix this is irrelevant
10184 
10185   Output Parameter:
10186 . D - the product matrix
10187 
10188   Level: intermediate
10189 
10190   Notes:
10191   Unless scall is `MAT_REUSE_MATRIX` D will be created.
10192 
10193   `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10194 
10195   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10196 
10197   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10198   actually needed.
10199 
10200   If you have many matrices with the same non-zero structure to multiply, you
10201   should use `MAT_REUSE_MATRIX` in all calls but the first
10202 
10203 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10204 @*/
10205 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10206 {
10207   PetscFunctionBegin;
10208   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10209   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10210 
10211   if (scall == MAT_INITIAL_MATRIX) {
10212     PetscCall(MatProductCreate(A, B, C, D));
10213     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10214     PetscCall(MatProductSetAlgorithm(*D, "default"));
10215     PetscCall(MatProductSetFill(*D, fill));
10216 
10217     (*D)->product->api_user = PETSC_TRUE;
10218     PetscCall(MatProductSetFromOptions(*D));
10219     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,
10220                ((PetscObject)C)->type_name);
10221     PetscCall(MatProductSymbolic(*D));
10222   } else { /* user may change input matrices when REUSE */
10223     PetscCall(MatProductReplaceMats(A, B, C, *D));
10224   }
10225   PetscCall(MatProductNumeric(*D));
10226   PetscFunctionReturn(PETSC_SUCCESS);
10227 }
10228 
10229 /*@
10230   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10231 
10232   Collective
10233 
10234   Input Parameters:
10235 + mat      - the matrix
10236 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10237 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10238 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10239 
10240   Output Parameter:
10241 . matredundant - redundant matrix
10242 
10243   Level: advanced
10244 
10245   Notes:
10246   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10247   original matrix has not changed from that last call to MatCreateRedundantMatrix().
10248 
10249   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10250   calling it.
10251 
10252   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10253 
10254 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10255 @*/
10256 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10257 {
10258   MPI_Comm       comm;
10259   PetscMPIInt    size;
10260   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10261   Mat_Redundant *redund     = NULL;
10262   PetscSubcomm   psubcomm   = NULL;
10263   MPI_Comm       subcomm_in = subcomm;
10264   Mat           *matseq;
10265   IS             isrow, iscol;
10266   PetscBool      newsubcomm = PETSC_FALSE;
10267 
10268   PetscFunctionBegin;
10269   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10270   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10271     PetscValidPointer(*matredundant, 5);
10272     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10273   }
10274 
10275   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10276   if (size == 1 || nsubcomm == 1) {
10277     if (reuse == MAT_INITIAL_MATRIX) {
10278       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10279     } else {
10280       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");
10281       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10282     }
10283     PetscFunctionReturn(PETSC_SUCCESS);
10284   }
10285 
10286   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10287   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10288   MatCheckPreallocated(mat, 1);
10289 
10290   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10291   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10292     /* create psubcomm, then get subcomm */
10293     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10294     PetscCallMPI(MPI_Comm_size(comm, &size));
10295     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10296 
10297     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10298     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10299     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10300     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10301     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10302     newsubcomm = PETSC_TRUE;
10303     PetscCall(PetscSubcommDestroy(&psubcomm));
10304   }
10305 
10306   /* get isrow, iscol and a local sequential matrix matseq[0] */
10307   if (reuse == MAT_INITIAL_MATRIX) {
10308     mloc_sub = PETSC_DECIDE;
10309     nloc_sub = PETSC_DECIDE;
10310     if (bs < 1) {
10311       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10312       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10313     } else {
10314       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10315       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10316     }
10317     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10318     rstart = rend - mloc_sub;
10319     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10320     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10321   } else { /* reuse == MAT_REUSE_MATRIX */
10322     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");
10323     /* retrieve subcomm */
10324     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10325     redund = (*matredundant)->redundant;
10326     isrow  = redund->isrow;
10327     iscol  = redund->iscol;
10328     matseq = redund->matseq;
10329   }
10330   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10331 
10332   /* get matredundant over subcomm */
10333   if (reuse == MAT_INITIAL_MATRIX) {
10334     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10335 
10336     /* create a supporting struct and attach it to C for reuse */
10337     PetscCall(PetscNew(&redund));
10338     (*matredundant)->redundant = redund;
10339     redund->isrow              = isrow;
10340     redund->iscol              = iscol;
10341     redund->matseq             = matseq;
10342     if (newsubcomm) {
10343       redund->subcomm = subcomm;
10344     } else {
10345       redund->subcomm = MPI_COMM_NULL;
10346     }
10347   } else {
10348     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10349   }
10350 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10351   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10352     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10353     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10354   }
10355 #endif
10356   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10357   PetscFunctionReturn(PETSC_SUCCESS);
10358 }
10359 
10360 /*@C
10361   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10362   a given `Mat`. Each submatrix can span multiple procs.
10363 
10364   Collective
10365 
10366   Input Parameters:
10367 + mat     - the matrix
10368 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10369 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10370 
10371   Output Parameter:
10372 . subMat - parallel sub-matrices each spanning a given `subcomm`
10373 
10374   Level: advanced
10375 
10376   Notes:
10377   The submatrix partition across processors is dictated by `subComm` a
10378   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10379   is not restricted to be grouped with consecutive original ranks.
10380 
10381   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10382   map directly to the layout of the original matrix [wrt the local
10383   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10384   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10385   the `subMat`. However the offDiagMat looses some columns - and this is
10386   reconstructed with `MatSetValues()`
10387 
10388   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10389 
10390 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10391 @*/
10392 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10393 {
10394   PetscMPIInt commsize, subCommSize;
10395 
10396   PetscFunctionBegin;
10397   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10398   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10399   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10400 
10401   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");
10402   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10403   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10404   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10405   PetscFunctionReturn(PETSC_SUCCESS);
10406 }
10407 
10408 /*@
10409   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10410 
10411   Not Collective
10412 
10413   Input Parameters:
10414 + mat   - matrix to extract local submatrix from
10415 . isrow - local row indices for submatrix
10416 - iscol - local column indices for submatrix
10417 
10418   Output Parameter:
10419 . submat - the submatrix
10420 
10421   Level: intermediate
10422 
10423   Notes:
10424   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10425 
10426   Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10427   the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10428 
10429   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10430   `MatSetValuesBlockedLocal()` will also be implemented.
10431 
10432   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10433   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10434 
10435 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10436 @*/
10437 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10438 {
10439   PetscFunctionBegin;
10440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10441   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10442   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10443   PetscCheckSameComm(isrow, 2, iscol, 3);
10444   PetscValidPointer(submat, 4);
10445   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10446 
10447   if (mat->ops->getlocalsubmatrix) {
10448     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10449   } else {
10450     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10451   }
10452   PetscFunctionReturn(PETSC_SUCCESS);
10453 }
10454 
10455 /*@
10456   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10457 
10458   Not Collective
10459 
10460   Input Parameters:
10461 + mat    - matrix to extract local submatrix from
10462 . isrow  - local row indices for submatrix
10463 . iscol  - local column indices for submatrix
10464 - submat - the submatrix
10465 
10466   Level: intermediate
10467 
10468 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10469 @*/
10470 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10471 {
10472   PetscFunctionBegin;
10473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10474   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10475   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10476   PetscCheckSameComm(isrow, 2, iscol, 3);
10477   PetscValidPointer(submat, 4);
10478   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10479 
10480   if (mat->ops->restorelocalsubmatrix) {
10481     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10482   } else {
10483     PetscCall(MatDestroy(submat));
10484   }
10485   *submat = NULL;
10486   PetscFunctionReturn(PETSC_SUCCESS);
10487 }
10488 
10489 /*@
10490   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10491 
10492   Collective
10493 
10494   Input Parameter:
10495 . mat - the matrix
10496 
10497   Output Parameter:
10498 . is - if any rows have zero diagonals this contains the list of them
10499 
10500   Level: developer
10501 
10502 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10503 @*/
10504 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10505 {
10506   PetscFunctionBegin;
10507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10508   PetscValidType(mat, 1);
10509   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10510   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10511 
10512   if (!mat->ops->findzerodiagonals) {
10513     Vec                diag;
10514     const PetscScalar *a;
10515     PetscInt          *rows;
10516     PetscInt           rStart, rEnd, r, nrow = 0;
10517 
10518     PetscCall(MatCreateVecs(mat, &diag, NULL));
10519     PetscCall(MatGetDiagonal(mat, diag));
10520     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10521     PetscCall(VecGetArrayRead(diag, &a));
10522     for (r = 0; r < rEnd - rStart; ++r)
10523       if (a[r] == 0.0) ++nrow;
10524     PetscCall(PetscMalloc1(nrow, &rows));
10525     nrow = 0;
10526     for (r = 0; r < rEnd - rStart; ++r)
10527       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10528     PetscCall(VecRestoreArrayRead(diag, &a));
10529     PetscCall(VecDestroy(&diag));
10530     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10531   } else {
10532     PetscUseTypeMethod(mat, findzerodiagonals, is);
10533   }
10534   PetscFunctionReturn(PETSC_SUCCESS);
10535 }
10536 
10537 /*@
10538   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10539 
10540   Collective
10541 
10542   Input Parameter:
10543 . mat - the matrix
10544 
10545   Output Parameter:
10546 . is - contains the list of rows with off block diagonal entries
10547 
10548   Level: developer
10549 
10550 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10551 @*/
10552 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10553 {
10554   PetscFunctionBegin;
10555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10556   PetscValidType(mat, 1);
10557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10559 
10560   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10561   PetscFunctionReturn(PETSC_SUCCESS);
10562 }
10563 
10564 /*@C
10565   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10566 
10567   Collective; No Fortran Support
10568 
10569   Input Parameter:
10570 . mat - the matrix
10571 
10572   Output Parameter:
10573 . values - the block inverses in column major order (FORTRAN-like)
10574 
10575   Level: advanced
10576 
10577   Notes:
10578   The size of the blocks is determined by the block size of the matrix.
10579 
10580   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10581 
10582   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10583 
10584 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10585 @*/
10586 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10587 {
10588   PetscFunctionBegin;
10589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10590   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10591   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10592   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10593   PetscFunctionReturn(PETSC_SUCCESS);
10594 }
10595 
10596 /*@C
10597   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10598 
10599   Collective; No Fortran Support
10600 
10601   Input Parameters:
10602 + mat     - the matrix
10603 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10604 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10605 
10606   Output Parameter:
10607 . values - the block inverses in column major order (FORTRAN-like)
10608 
10609   Level: advanced
10610 
10611   Notes:
10612   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10613 
10614   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10615 
10616 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10617 @*/
10618 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10619 {
10620   PetscFunctionBegin;
10621   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10622   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10623   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10624   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10625   PetscFunctionReturn(PETSC_SUCCESS);
10626 }
10627 
10628 /*@
10629   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10630 
10631   Collective
10632 
10633   Input Parameters:
10634 + A - the matrix
10635 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10636 
10637   Level: advanced
10638 
10639   Note:
10640   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10641 
10642 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10643 @*/
10644 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10645 {
10646   const PetscScalar *vals;
10647   PetscInt          *dnnz;
10648   PetscInt           m, rstart, rend, bs, i, j;
10649 
10650   PetscFunctionBegin;
10651   PetscCall(MatInvertBlockDiagonal(A, &vals));
10652   PetscCall(MatGetBlockSize(A, &bs));
10653   PetscCall(MatGetLocalSize(A, &m, NULL));
10654   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10655   PetscCall(PetscMalloc1(m / bs, &dnnz));
10656   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10657   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10658   PetscCall(PetscFree(dnnz));
10659   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10660   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10661   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10662   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10663   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10664   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10665   PetscFunctionReturn(PETSC_SUCCESS);
10666 }
10667 
10668 /*@C
10669   MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10670   via `MatTransposeColoringCreate()`.
10671 
10672   Collective
10673 
10674   Input Parameter:
10675 . c - coloring context
10676 
10677   Level: intermediate
10678 
10679 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10680 @*/
10681 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10682 {
10683   MatTransposeColoring matcolor = *c;
10684 
10685   PetscFunctionBegin;
10686   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10687   if (--((PetscObject)matcolor)->refct > 0) {
10688     matcolor = NULL;
10689     PetscFunctionReturn(PETSC_SUCCESS);
10690   }
10691 
10692   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10693   PetscCall(PetscFree(matcolor->rows));
10694   PetscCall(PetscFree(matcolor->den2sp));
10695   PetscCall(PetscFree(matcolor->colorforcol));
10696   PetscCall(PetscFree(matcolor->columns));
10697   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10698   PetscCall(PetscHeaderDestroy(c));
10699   PetscFunctionReturn(PETSC_SUCCESS);
10700 }
10701 
10702 /*@C
10703   MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10704   a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10705   `MatTransposeColoring` to sparse B.
10706 
10707   Collective
10708 
10709   Input Parameters:
10710 + coloring - coloring context created with `MatTransposeColoringCreate()`
10711 - B        - sparse matrix
10712 
10713   Output Parameter:
10714 . Btdense - dense matrix B^T
10715 
10716   Level: developer
10717 
10718   Note:
10719   These are used internally for some implementations of `MatRARt()`
10720 
10721 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10722 @*/
10723 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10724 {
10725   PetscFunctionBegin;
10726   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10727   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10728   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10729 
10730   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10731   PetscFunctionReturn(PETSC_SUCCESS);
10732 }
10733 
10734 /*@C
10735   MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10736   a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10737   in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10738   `Csp` from `Cden`.
10739 
10740   Collective
10741 
10742   Input Parameters:
10743 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10744 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10745 
10746   Output Parameter:
10747 . Csp - sparse matrix
10748 
10749   Level: developer
10750 
10751   Note:
10752   These are used internally for some implementations of `MatRARt()`
10753 
10754 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10755 @*/
10756 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10757 {
10758   PetscFunctionBegin;
10759   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10760   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10761   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10762 
10763   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10764   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10765   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10766   PetscFunctionReturn(PETSC_SUCCESS);
10767 }
10768 
10769 /*@C
10770   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10771 
10772   Collective
10773 
10774   Input Parameters:
10775 + mat        - the matrix product C
10776 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10777 
10778   Output Parameter:
10779 . color - the new coloring context
10780 
10781   Level: intermediate
10782 
10783 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10784           `MatTransColoringApplyDenToSp()`
10785 @*/
10786 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10787 {
10788   MatTransposeColoring c;
10789   MPI_Comm             comm;
10790 
10791   PetscFunctionBegin;
10792   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10793   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10794   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10795 
10796   c->ctype = iscoloring->ctype;
10797   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10798 
10799   *color = c;
10800   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10801   PetscFunctionReturn(PETSC_SUCCESS);
10802 }
10803 
10804 /*@
10805   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10806   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10807   same, otherwise it will be larger
10808 
10809   Not Collective
10810 
10811   Input Parameter:
10812 . mat - the matrix
10813 
10814   Output Parameter:
10815 . state - the current state
10816 
10817   Level: intermediate
10818 
10819   Notes:
10820   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10821   different matrices
10822 
10823   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10824 
10825   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10826 
10827 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10828 @*/
10829 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10830 {
10831   PetscFunctionBegin;
10832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10833   *state = mat->nonzerostate;
10834   PetscFunctionReturn(PETSC_SUCCESS);
10835 }
10836 
10837 /*@
10838   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10839   matrices from each processor
10840 
10841   Collective
10842 
10843   Input Parameters:
10844 + comm   - the communicators the parallel matrix will live on
10845 . seqmat - the input sequential matrices
10846 . n      - number of local columns (or `PETSC_DECIDE`)
10847 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10848 
10849   Output Parameter:
10850 . mpimat - the parallel matrix generated
10851 
10852   Level: developer
10853 
10854   Note:
10855   The number of columns of the matrix in EACH processor MUST be the same.
10856 
10857 .seealso: [](ch_matrices), `Mat`
10858 @*/
10859 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10860 {
10861   PetscMPIInt size;
10862 
10863   PetscFunctionBegin;
10864   PetscCallMPI(MPI_Comm_size(comm, &size));
10865   if (size == 1) {
10866     if (reuse == MAT_INITIAL_MATRIX) {
10867       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10868     } else {
10869       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10870     }
10871     PetscFunctionReturn(PETSC_SUCCESS);
10872   }
10873 
10874   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");
10875 
10876   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10877   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10878   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10879   PetscFunctionReturn(PETSC_SUCCESS);
10880 }
10881 
10882 /*@
10883   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10884 
10885   Collective
10886 
10887   Input Parameters:
10888 + A - the matrix to create subdomains from
10889 - N - requested number of subdomains
10890 
10891   Output Parameters:
10892 + n   - number of subdomains resulting on this MPI process
10893 - iss - `IS` list with indices of subdomains on this MPI process
10894 
10895   Level: advanced
10896 
10897   Note:
10898   The number of subdomains must be smaller than the communicator size
10899 
10900 .seealso: [](ch_matrices), `Mat`, `IS`
10901 @*/
10902 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10903 {
10904   MPI_Comm    comm, subcomm;
10905   PetscMPIInt size, rank, color;
10906   PetscInt    rstart, rend, k;
10907 
10908   PetscFunctionBegin;
10909   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10910   PetscCallMPI(MPI_Comm_size(comm, &size));
10911   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10912   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);
10913   *n    = 1;
10914   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10915   color = rank / k;
10916   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10917   PetscCall(PetscMalloc1(1, iss));
10918   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10919   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10920   PetscCallMPI(MPI_Comm_free(&subcomm));
10921   PetscFunctionReturn(PETSC_SUCCESS);
10922 }
10923 
10924 /*@
10925   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10926 
10927   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10928   If they are not the same, uses `MatMatMatMult()`.
10929 
10930   Once the coarse grid problem is constructed, correct for interpolation operators
10931   that are not of full rank, which can legitimately happen in the case of non-nested
10932   geometric multigrid.
10933 
10934   Input Parameters:
10935 + restrct     - restriction operator
10936 . dA          - fine grid matrix
10937 . interpolate - interpolation operator
10938 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10939 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10940 
10941   Output Parameter:
10942 . A - the Galerkin coarse matrix
10943 
10944   Options Database Key:
10945 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10946 
10947   Level: developer
10948 
10949 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10950 @*/
10951 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10952 {
10953   IS  zerorows;
10954   Vec diag;
10955 
10956   PetscFunctionBegin;
10957   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10958   /* Construct the coarse grid matrix */
10959   if (interpolate == restrct) {
10960     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10961   } else {
10962     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10963   }
10964 
10965   /* If the interpolation matrix is not of full rank, A will have zero rows.
10966      This can legitimately happen in the case of non-nested geometric multigrid.
10967      In that event, we set the rows of the matrix to the rows of the identity,
10968      ignoring the equations (as the RHS will also be zero). */
10969 
10970   PetscCall(MatFindZeroRows(*A, &zerorows));
10971 
10972   if (zerorows != NULL) { /* if there are any zero rows */
10973     PetscCall(MatCreateVecs(*A, &diag, NULL));
10974     PetscCall(MatGetDiagonal(*A, diag));
10975     PetscCall(VecISSet(diag, zerorows, 1.0));
10976     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10977     PetscCall(VecDestroy(&diag));
10978     PetscCall(ISDestroy(&zerorows));
10979   }
10980   PetscFunctionReturn(PETSC_SUCCESS);
10981 }
10982 
10983 /*@C
10984   MatSetOperation - Allows user to set a matrix operation for any matrix type
10985 
10986   Logically Collective
10987 
10988   Input Parameters:
10989 + mat - the matrix
10990 . op  - the name of the operation
10991 - f   - the function that provides the operation
10992 
10993   Level: developer
10994 
10995   Example Usage:
10996 .vb
10997   extern PetscErrorCode usermult(Mat, Vec, Vec);
10998 
10999   PetscCall(MatCreateXXX(comm, ..., &A));
11000   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11001 .ve
11002 
11003   Notes:
11004   See the file `include/petscmat.h` for a complete list of matrix
11005   operations, which all have the form MATOP_<OPERATION>, where
11006   <OPERATION> is the name (in all capital letters) of the
11007   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11008 
11009   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11010   sequence as the usual matrix interface routines, since they
11011   are intended to be accessed via the usual matrix interface
11012   routines, e.g.,
11013 .vb
11014   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11015 .ve
11016 
11017   In particular each function MUST return `PETSC_SUCCESS` on success and
11018   nonzero on failure.
11019 
11020   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11021 
11022 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11023 @*/
11024 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11025 {
11026   PetscFunctionBegin;
11027   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11028   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11029   (((void (**)(void))mat->ops)[op]) = f;
11030   PetscFunctionReturn(PETSC_SUCCESS);
11031 }
11032 
11033 /*@C
11034   MatGetOperation - Gets a matrix operation for any matrix type.
11035 
11036   Not Collective
11037 
11038   Input Parameters:
11039 + mat - the matrix
11040 - op  - the name of the operation
11041 
11042   Output Parameter:
11043 . f - the function that provides the operation
11044 
11045   Level: developer
11046 
11047   Example Usage:
11048 .vb
11049   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11050 
11051   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11052 .ve
11053 
11054   Notes:
11055   See the file include/petscmat.h for a complete list of matrix
11056   operations, which all have the form MATOP_<OPERATION>, where
11057   <OPERATION> is the name (in all capital letters) of the
11058   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11059 
11060   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11061 
11062 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11063 @*/
11064 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11065 {
11066   PetscFunctionBegin;
11067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11068   *f = (((void (**)(void))mat->ops)[op]);
11069   PetscFunctionReturn(PETSC_SUCCESS);
11070 }
11071 
11072 /*@
11073   MatHasOperation - Determines whether the given matrix supports the particular operation.
11074 
11075   Not Collective
11076 
11077   Input Parameters:
11078 + mat - the matrix
11079 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11080 
11081   Output Parameter:
11082 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11083 
11084   Level: advanced
11085 
11086   Note:
11087   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11088 
11089 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11090 @*/
11091 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11092 {
11093   PetscFunctionBegin;
11094   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11095   PetscValidBoolPointer(has, 3);
11096   if (mat->ops->hasoperation) {
11097     PetscUseTypeMethod(mat, hasoperation, op, has);
11098   } else {
11099     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11100     else {
11101       *has = PETSC_FALSE;
11102       if (op == MATOP_CREATE_SUBMATRIX) {
11103         PetscMPIInt size;
11104 
11105         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11106         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11107       }
11108     }
11109   }
11110   PetscFunctionReturn(PETSC_SUCCESS);
11111 }
11112 
11113 /*@
11114   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11115 
11116   Collective
11117 
11118   Input Parameter:
11119 . mat - the matrix
11120 
11121   Output Parameter:
11122 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11123 
11124   Level: beginner
11125 
11126 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11127 @*/
11128 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11129 {
11130   PetscFunctionBegin;
11131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11132   PetscValidType(mat, 1);
11133   PetscValidBoolPointer(cong, 2);
11134   if (!mat->rmap || !mat->cmap) {
11135     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11136     PetscFunctionReturn(PETSC_SUCCESS);
11137   }
11138   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11139     PetscCall(PetscLayoutSetUp(mat->rmap));
11140     PetscCall(PetscLayoutSetUp(mat->cmap));
11141     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11142     if (*cong) mat->congruentlayouts = 1;
11143     else mat->congruentlayouts = 0;
11144   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11145   PetscFunctionReturn(PETSC_SUCCESS);
11146 }
11147 
11148 PetscErrorCode MatSetInf(Mat A)
11149 {
11150   PetscFunctionBegin;
11151   PetscUseTypeMethod(A, setinf);
11152   PetscFunctionReturn(PETSC_SUCCESS);
11153 }
11154 
11155 /*@C
11156   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
11157   and possibly removes small values from the graph structure.
11158 
11159   Collective
11160 
11161   Input Parameters:
11162 + A      - the matrix
11163 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11164 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11165 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11166 
11167   Output Parameter:
11168 . graph - the resulting graph
11169 
11170   Level: advanced
11171 
11172 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11173 @*/
11174 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11175 {
11176   PetscFunctionBegin;
11177   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11178   PetscValidType(A, 1);
11179   PetscValidLogicalCollectiveBool(A, scale, 3);
11180   PetscValidPointer(graph, 5);
11181   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11182   PetscFunctionReturn(PETSC_SUCCESS);
11183 }
11184 
11185 /*@
11186   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11187   meaning the same memory is used for the matrix, and no new memory is allocated.
11188 
11189   Collective
11190 
11191   Input Parameter:
11192 . A - the matrix
11193 
11194   Level: intermediate
11195 
11196   Developer Notes:
11197   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11198   of the arrays in the data structure are unneeded.
11199 
11200 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11201 @*/
11202 PetscErrorCode MatEliminateZeros(Mat A)
11203 {
11204   PetscFunctionBegin;
11205   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11206   PetscUseTypeMethod(A, eliminatezeros);
11207   PetscFunctionReturn(PETSC_SUCCESS);
11208 }
11209