xref: /petsc/src/mat/interface/matrix.c (revision bcd3bd92eda2d5998e2f14c4bbfb33bd936bdc3e)
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   PetscAssertPointer(pivot, 2);
136   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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) PetscAssertPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657   Not Collective
658 
659   Input Parameter:
660 . mat - the matrix
661 
662   Level: advanced
663 
664   Note:
665   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
666 
667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685   Not Collective
686 
687   Input Parameter:
688 . mat - the matrix
689 
690   Level: advanced
691 
692   Note:
693   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711   MatSetOptionsPrefix - Sets the prefix used for searching for all
712   `Mat` options in the database.
713 
714   Logically Collective
715 
716   Input Parameters:
717 + A      - the matrix
718 - prefix - the prefix to prepend to all option names
719 
720   Level: advanced
721 
722   Notes:
723   A hyphen (-) must NOT be given at the beginning of the prefix name.
724   The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726   This is NOT used for options for the factorization of the matrix. Normally the
727   prefix is automatically passed in from the PC calling the factorization. To set
728   it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742   for matrices created with `MatGetFactor()`
743 
744   Logically Collective
745 
746   Input Parameters:
747 + A      - the matrix
748 - prefix - the prefix to prepend to all option names for the factored matrix
749 
750   Level: developer
751 
752   Notes:
753   A hyphen (-) must NOT be given at the beginning of the prefix name.
754   The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscAssertPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778   for matrices created with `MatGetFactor()`
779 
780   Logically Collective
781 
782   Input Parameters:
783 + A      - the matrix
784 - prefix - the prefix to prepend to all option names for the factored matrix
785 
786   Level: developer
787 
788   Notes:
789   A hyphen (-) must NOT be given at the beginning of the prefix name.
790   The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822   matrix options in the database.
823 
824   Logically Collective
825 
826   Input Parameters:
827 + A      - the matrix
828 - prefix - the prefix to prepend to all option names
829 
830   Level: advanced
831 
832   Note:
833   A hyphen (-) must NOT be given at the beginning of the prefix name.
834   The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847   MatGetOptionsPrefix - Gets the prefix used for searching for all
848   matrix options in the database.
849 
850   Not Collective
851 
852   Input Parameter:
853 . A - the matrix
854 
855   Output Parameter:
856 . prefix - pointer to the prefix string used
857 
858   Level: advanced
859 
860   Fortran 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   PetscAssertPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by 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   PetscAssertPointer(idxm, 3);
1473   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(idxm, 3);
1735   PetscAssertPointer(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   PetscAssertPointer(idxm, 3);
1845   PetscAssertPointer(idxn, 5);
1846   PetscAssertPointer(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   PetscAssertPointer(dims, 3);
1911   PetscAssertPointer(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   PetscAssertPointer(idxm, 3);
2000   PetscAssertPointer(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   PetscAssertPointer(idxm, 3);
2094   PetscAssertPointer(idxn, 5);
2095   PetscAssertPointer(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   PetscAssertPointer(irow, 3);
2147   PetscAssertPointer(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   PetscAssertPointer(rows, 4);
2205   PetscAssertPointer(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     PetscAssertPointer(rmapping, 2);
2274     *rmapping = A->rmap->mapping;
2275   }
2276   if (cmapping) {
2277     PetscAssertPointer(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     PetscAssertPointer(rmap, 2);
2332     *rmap = A->rmap;
2333   }
2334   if (cmap) {
2335     PetscAssertPointer(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   PetscAssertPointer(irow, 3);
2386   PetscAssertPointer(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   PetscAssertPointer(irow, 3);
2474   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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) PetscAssertPointer(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   PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(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) PetscAssertPointer(m, 2);
6706   if (n) PetscAssertPointer(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) PetscAssertPointer(m, 2);
6739   if (n) PetscAssertPointer(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) PetscAssertPointer(m, 2);
6775   if (n) PetscAssertPointer(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   PetscAssertPointer(info, 5);
6930   PetscAssertPointer(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   PetscAssertPointer(info, 4);
6985   PetscAssertPointer(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     PetscAssertPointer(irow, 3);
7061     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7062     PetscAssertPointer(icol, 4);
7063     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7064   }
7065   PetscAssertPointer(submat, 6);
7066   if (n && scall == MAT_REUSE_MATRIX) {
7067     PetscAssertPointer(*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     PetscAssertPointer(irow, 3);
7122     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7123     PetscAssertPointer(icol, 4);
7124     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7125   }
7126   PetscAssertPointer(submat, 6);
7127   if (n && scall == MAT_REUSE_MATRIX) {
7128     PetscAssertPointer(*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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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   PetscAssertPointer(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     PetscAssertPointer(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     PetscAssertPointer(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   PetscAssertPointer(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) PetscAssertPointer(rbs, 2);
7427   if (cbs) PetscAssertPointer(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   Level: intermediate
7488 
7489   Notes:
7490   There can be zeros within the blocks
7491 
7492   The blocks can overlap between processes, including laying on more than two processes
7493 
7494 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7495 @*/
7496 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7497 {
7498   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7499   PetscInt          *diag, *odiag, sc;
7500   VecScatter         scatter;
7501   PetscScalar       *seqv;
7502   const PetscScalar *parv;
7503   const PetscInt    *ia, *ja;
7504   PetscBool          set, flag, done;
7505   Mat                AA = mat, A;
7506   MPI_Comm           comm;
7507   PetscMPIInt        rank, size, tag;
7508   MPI_Status         status;
7509   PetscContainer     container;
7510   EnvelopeData      *edata;
7511   Vec                seq, par;
7512   IS                 isglobal;
7513 
7514   PetscFunctionBegin;
7515   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7516   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7517   if (!set || !flag) {
7518     /* TODO: only needs nonzero structure of transpose */
7519     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7520     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7521   }
7522   PetscCall(MatAIJGetLocalMat(AA, &A));
7523   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7524   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7525 
7526   PetscCall(MatGetLocalSize(mat, &n, NULL));
7527   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7528   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7529   PetscCallMPI(MPI_Comm_size(comm, &size));
7530   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7531 
7532   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7533 
7534   if (rank > 0) {
7535     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7536     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7537   }
7538   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7539   for (i = 0; i < n; i++) {
7540     env = PetscMax(env, ja[ia[i + 1] - 1]);
7541     II  = rstart + i;
7542     if (env == II) {
7543       starts[lblocks]  = tbs;
7544       sizes[lblocks++] = 1 + II - tbs;
7545       tbs              = 1 + II;
7546     }
7547   }
7548   if (rank < size - 1) {
7549     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7550     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7551   }
7552 
7553   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7554   if (!set || !flag) PetscCall(MatDestroy(&AA));
7555   PetscCall(MatDestroy(&A));
7556 
7557   PetscCall(PetscNew(&edata));
7558   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7559   edata->n = lblocks;
7560   /* create IS needed for extracting blocks from the original matrix */
7561   PetscCall(PetscMalloc1(lblocks, &edata->is));
7562   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7563 
7564   /* Create the resulting inverse matrix structure with preallocation information */
7565   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7566   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7567   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7568   PetscCall(MatSetType(edata->C, MATAIJ));
7569 
7570   /* Communicate the start and end of each row, from each block to the correct rank */
7571   /* TODO: Use PetscSF instead of VecScatter */
7572   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7573   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7574   PetscCall(VecGetArrayWrite(seq, &seqv));
7575   for (PetscInt i = 0; i < lblocks; i++) {
7576     for (PetscInt j = 0; j < sizes[i]; j++) {
7577       seqv[cnt]     = starts[i];
7578       seqv[cnt + 1] = starts[i] + sizes[i];
7579       cnt += 2;
7580     }
7581   }
7582   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7583   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7584   sc -= cnt;
7585   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7586   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7587   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7588   PetscCall(ISDestroy(&isglobal));
7589   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7590   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7591   PetscCall(VecScatterDestroy(&scatter));
7592   PetscCall(VecDestroy(&seq));
7593   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7594   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7595   PetscCall(VecGetArrayRead(par, &parv));
7596   cnt = 0;
7597   PetscCall(MatGetSize(mat, NULL, &n));
7598   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7599     PetscInt start, end, d = 0, od = 0;
7600 
7601     start = (PetscInt)PetscRealPart(parv[cnt]);
7602     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7603     cnt += 2;
7604 
7605     if (start < cstart) {
7606       od += cstart - start + n - cend;
7607       d += cend - cstart;
7608     } else if (start < cend) {
7609       od += n - cend;
7610       d += cend - start;
7611     } else od += n - start;
7612     if (end <= cstart) {
7613       od -= cstart - end + n - cend;
7614       d -= cend - cstart;
7615     } else if (end < cend) {
7616       od -= n - cend;
7617       d -= cend - end;
7618     } else od -= n - end;
7619 
7620     odiag[i] = od;
7621     diag[i]  = d;
7622   }
7623   PetscCall(VecRestoreArrayRead(par, &parv));
7624   PetscCall(VecDestroy(&par));
7625   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7626   PetscCall(PetscFree2(diag, odiag));
7627   PetscCall(PetscFree2(sizes, starts));
7628 
7629   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7630   PetscCall(PetscContainerSetPointer(container, edata));
7631   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7632   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7633   PetscCall(PetscObjectDereference((PetscObject)container));
7634   PetscFunctionReturn(PETSC_SUCCESS);
7635 }
7636 
7637 /*@
7638   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7639 
7640   Collective
7641 
7642   Input Parameters:
7643 + A     - the matrix
7644 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7645 
7646   Output Parameter:
7647 . C - matrix with inverted block diagonal of `A`
7648 
7649   Level: advanced
7650 
7651   Note:
7652   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7653 
7654 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7655 @*/
7656 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7657 {
7658   PetscContainer   container;
7659   EnvelopeData    *edata;
7660   PetscObjectState nonzerostate;
7661 
7662   PetscFunctionBegin;
7663   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7664   if (!container) {
7665     PetscCall(MatComputeVariableBlockEnvelope(A));
7666     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7667   }
7668   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7669   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7670   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7671   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7672 
7673   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7674   *C = edata->C;
7675 
7676   for (PetscInt i = 0; i < edata->n; i++) {
7677     Mat          D;
7678     PetscScalar *dvalues;
7679 
7680     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7681     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7682     PetscCall(MatSeqDenseInvert(D));
7683     PetscCall(MatDenseGetArray(D, &dvalues));
7684     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7685     PetscCall(MatDestroy(&D));
7686   }
7687   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7688   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7689   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7690   PetscFunctionReturn(PETSC_SUCCESS);
7691 }
7692 
7693 /*@
7694   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7695 
7696   Logically Collective
7697 
7698   Input Parameters:
7699 + mat     - the matrix
7700 . nblocks - the number of blocks on this process, each block can only exist on a single process
7701 - bsizes  - the block sizes
7702 
7703   Level: intermediate
7704 
7705   Notes:
7706   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7707 
7708   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.
7709 
7710 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7711           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7712 @*/
7713 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7714 {
7715   PetscInt i, ncnt = 0, nlocal;
7716 
7717   PetscFunctionBegin;
7718   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7719   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7720   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7721   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7722   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);
7723   PetscCall(PetscFree(mat->bsizes));
7724   mat->nblocks = nblocks;
7725   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7726   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7727   PetscFunctionReturn(PETSC_SUCCESS);
7728 }
7729 
7730 /*@C
7731   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7732 
7733   Logically Collective; No Fortran Support
7734 
7735   Input Parameter:
7736 . mat - the matrix
7737 
7738   Output Parameters:
7739 + nblocks - the number of blocks on this process
7740 - bsizes  - the block sizes
7741 
7742   Level: intermediate
7743 
7744 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7745 @*/
7746 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7747 {
7748   PetscFunctionBegin;
7749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7750   *nblocks = mat->nblocks;
7751   *bsizes  = mat->bsizes;
7752   PetscFunctionReturn(PETSC_SUCCESS);
7753 }
7754 
7755 /*@
7756   MatSetBlockSizes - Sets the matrix block row and column sizes.
7757 
7758   Logically Collective
7759 
7760   Input Parameters:
7761 + mat - the matrix
7762 . rbs - row block size
7763 - cbs - column block size
7764 
7765   Level: intermediate
7766 
7767   Notes:
7768   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7769   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7770   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7771 
7772   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7773   are compatible with the matrix local sizes.
7774 
7775   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7776 
7777 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7778 @*/
7779 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7780 {
7781   PetscFunctionBegin;
7782   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7783   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7784   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7785   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7786   if (mat->rmap->refcnt) {
7787     ISLocalToGlobalMapping l2g  = NULL;
7788     PetscLayout            nmap = NULL;
7789 
7790     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7791     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7792     PetscCall(PetscLayoutDestroy(&mat->rmap));
7793     mat->rmap          = nmap;
7794     mat->rmap->mapping = l2g;
7795   }
7796   if (mat->cmap->refcnt) {
7797     ISLocalToGlobalMapping l2g  = NULL;
7798     PetscLayout            nmap = NULL;
7799 
7800     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7801     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7802     PetscCall(PetscLayoutDestroy(&mat->cmap));
7803     mat->cmap          = nmap;
7804     mat->cmap->mapping = l2g;
7805   }
7806   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7807   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7808   PetscFunctionReturn(PETSC_SUCCESS);
7809 }
7810 
7811 /*@
7812   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7813 
7814   Logically Collective
7815 
7816   Input Parameters:
7817 + mat     - the matrix
7818 . fromRow - matrix from which to copy row block size
7819 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7820 
7821   Level: developer
7822 
7823 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7824 @*/
7825 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7826 {
7827   PetscFunctionBegin;
7828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7829   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7830   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7831   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7832   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7833   PetscFunctionReturn(PETSC_SUCCESS);
7834 }
7835 
7836 /*@
7837   MatResidual - Default routine to calculate the residual r = b - Ax
7838 
7839   Collective
7840 
7841   Input Parameters:
7842 + mat - the matrix
7843 . b   - the right-hand-side
7844 - x   - the approximate solution
7845 
7846   Output Parameter:
7847 . r - location to store the residual
7848 
7849   Level: developer
7850 
7851 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7852 @*/
7853 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7854 {
7855   PetscFunctionBegin;
7856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7857   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7858   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7859   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7860   PetscValidType(mat, 1);
7861   MatCheckPreallocated(mat, 1);
7862   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7863   if (!mat->ops->residual) {
7864     PetscCall(MatMult(mat, x, r));
7865     PetscCall(VecAYPX(r, -1.0, b));
7866   } else {
7867     PetscUseTypeMethod(mat, residual, b, x, r);
7868   }
7869   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7870   PetscFunctionReturn(PETSC_SUCCESS);
7871 }
7872 
7873 /*MC
7874     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7875 
7876     Synopsis:
7877     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7878 
7879     Not Collective
7880 
7881     Input Parameters:
7882 +   A - the matrix
7883 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7884 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7885 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7886                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7887                  always used.
7888 
7889     Output Parameters:
7890 +   n - number of local rows in the (possibly compressed) matrix
7891 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7892 .   ja - the column indices
7893 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7894            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7895 
7896     Level: developer
7897 
7898     Note:
7899     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7900 
7901 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7902 M*/
7903 
7904 /*MC
7905     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7906 
7907     Synopsis:
7908     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7909 
7910     Not Collective
7911 
7912     Input Parameters:
7913 +   A - the  matrix
7914 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7915 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7916     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7917                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7918                  always used.
7919 .   n - number of local rows in the (possibly compressed) matrix
7920 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7921 .   ja - the column indices
7922 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7923            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7924 
7925     Level: developer
7926 
7927 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7928 M*/
7929 
7930 /*@C
7931   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7932 
7933   Collective
7934 
7935   Input Parameters:
7936 + mat             - the matrix
7937 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7938 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7939 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7940                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7941                  always used.
7942 
7943   Output Parameters:
7944 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7945 . 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
7946 . ja   - the column indices, use `NULL` if not needed
7947 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7948            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7949 
7950   Level: developer
7951 
7952   Notes:
7953   You CANNOT change any of the ia[] or ja[] values.
7954 
7955   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7956 
7957   Fortran Notes:
7958   Use
7959 .vb
7960     PetscInt, pointer :: ia(:),ja(:)
7961     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7962     ! Access the ith and jth entries via ia(i) and ja(j)
7963 .ve
7964   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7965 
7966 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7967 @*/
7968 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7969 {
7970   PetscFunctionBegin;
7971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7972   PetscValidType(mat, 1);
7973   if (n) PetscAssertPointer(n, 5);
7974   if (ia) PetscAssertPointer(ia, 6);
7975   if (ja) PetscAssertPointer(ja, 7);
7976   if (done) PetscAssertPointer(done, 8);
7977   MatCheckPreallocated(mat, 1);
7978   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7979   else {
7980     if (done) *done = PETSC_TRUE;
7981     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7982     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7983     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7984   }
7985   PetscFunctionReturn(PETSC_SUCCESS);
7986 }
7987 
7988 /*@C
7989   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7990 
7991   Collective
7992 
7993   Input Parameters:
7994 + mat             - the matrix
7995 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
7996 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7997                 symmetrized
7998 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7999                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8000                  always used.
8001 . n               - number of columns in the (possibly compressed) matrix
8002 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8003 - ja              - the row indices
8004 
8005   Output Parameter:
8006 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8007 
8008   Level: developer
8009 
8010 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8011 @*/
8012 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8013 {
8014   PetscFunctionBegin;
8015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8016   PetscValidType(mat, 1);
8017   PetscAssertPointer(n, 5);
8018   if (ia) PetscAssertPointer(ia, 6);
8019   if (ja) PetscAssertPointer(ja, 7);
8020   PetscAssertPointer(done, 8);
8021   MatCheckPreallocated(mat, 1);
8022   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8023   else {
8024     *done = PETSC_TRUE;
8025     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8026   }
8027   PetscFunctionReturn(PETSC_SUCCESS);
8028 }
8029 
8030 /*@C
8031   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8032 
8033   Collective
8034 
8035   Input Parameters:
8036 + mat             - the matrix
8037 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8038 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8039 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8040                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8041                  always used.
8042 . n               - size of (possibly compressed) matrix
8043 . ia              - the row pointers
8044 - ja              - the column indices
8045 
8046   Output Parameter:
8047 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8048 
8049   Level: developer
8050 
8051   Note:
8052   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8053   us of the array after it has been restored. If you pass `NULL`, it will
8054   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8055 
8056   Fortran Notes:
8057   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8058 
8059 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8060 @*/
8061 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8062 {
8063   PetscFunctionBegin;
8064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8065   PetscValidType(mat, 1);
8066   if (ia) PetscAssertPointer(ia, 6);
8067   if (ja) PetscAssertPointer(ja, 7);
8068   if (done) PetscAssertPointer(done, 8);
8069   MatCheckPreallocated(mat, 1);
8070 
8071   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8072   else {
8073     if (done) *done = PETSC_TRUE;
8074     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8075     if (n) *n = 0;
8076     if (ia) *ia = NULL;
8077     if (ja) *ja = NULL;
8078   }
8079   PetscFunctionReturn(PETSC_SUCCESS);
8080 }
8081 
8082 /*@C
8083   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8084 
8085   Collective
8086 
8087   Input Parameters:
8088 + mat             - the matrix
8089 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8090 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8091 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8092                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8093                  always used.
8094 
8095   Output Parameters:
8096 + n    - size of (possibly compressed) matrix
8097 . ia   - the column pointers
8098 . ja   - the row indices
8099 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8100 
8101   Level: developer
8102 
8103 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8104 @*/
8105 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8106 {
8107   PetscFunctionBegin;
8108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8109   PetscValidType(mat, 1);
8110   if (ia) PetscAssertPointer(ia, 6);
8111   if (ja) PetscAssertPointer(ja, 7);
8112   PetscAssertPointer(done, 8);
8113   MatCheckPreallocated(mat, 1);
8114 
8115   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8116   else {
8117     *done = PETSC_TRUE;
8118     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8119     if (n) *n = 0;
8120     if (ia) *ia = NULL;
8121     if (ja) *ja = NULL;
8122   }
8123   PetscFunctionReturn(PETSC_SUCCESS);
8124 }
8125 
8126 /*@C
8127   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8128   `MatGetColumnIJ()`.
8129 
8130   Collective
8131 
8132   Input Parameters:
8133 + mat        - the matrix
8134 . ncolors    - maximum color value
8135 . n          - number of entries in colorarray
8136 - colorarray - array indicating color for each column
8137 
8138   Output Parameter:
8139 . iscoloring - coloring generated using colorarray information
8140 
8141   Level: developer
8142 
8143 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8144 @*/
8145 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8146 {
8147   PetscFunctionBegin;
8148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8149   PetscValidType(mat, 1);
8150   PetscAssertPointer(colorarray, 4);
8151   PetscAssertPointer(iscoloring, 5);
8152   MatCheckPreallocated(mat, 1);
8153 
8154   if (!mat->ops->coloringpatch) {
8155     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8156   } else {
8157     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8158   }
8159   PetscFunctionReturn(PETSC_SUCCESS);
8160 }
8161 
8162 /*@
8163   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8164 
8165   Logically Collective
8166 
8167   Input Parameter:
8168 . mat - the factored matrix to be reset
8169 
8170   Level: developer
8171 
8172   Notes:
8173   This routine should be used only with factored matrices formed by in-place
8174   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8175   format).  This option can save memory, for example, when solving nonlinear
8176   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8177   ILU(0) preconditioner.
8178 
8179   One can specify in-place ILU(0) factorization by calling
8180 .vb
8181      PCType(pc,PCILU);
8182      PCFactorSeUseInPlace(pc);
8183 .ve
8184   or by using the options -pc_type ilu -pc_factor_in_place
8185 
8186   In-place factorization ILU(0) can also be used as a local
8187   solver for the blocks within the block Jacobi or additive Schwarz
8188   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8189   for details on setting local solver options.
8190 
8191   Most users should employ the `KSP` interface for linear solvers
8192   instead of working directly with matrix algebra routines such as this.
8193   See, e.g., `KSPCreate()`.
8194 
8195 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8196 @*/
8197 PetscErrorCode MatSetUnfactored(Mat mat)
8198 {
8199   PetscFunctionBegin;
8200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8201   PetscValidType(mat, 1);
8202   MatCheckPreallocated(mat, 1);
8203   mat->factortype = MAT_FACTOR_NONE;
8204   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8205   PetscUseTypeMethod(mat, setunfactored);
8206   PetscFunctionReturn(PETSC_SUCCESS);
8207 }
8208 
8209 /*MC
8210     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8211 
8212     Synopsis:
8213     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8214 
8215     Not Collective
8216 
8217     Input Parameter:
8218 .   x - matrix
8219 
8220     Output Parameters:
8221 +   xx_v - the Fortran pointer to the array
8222 -   ierr - error code
8223 
8224     Example of Usage:
8225 .vb
8226       PetscScalar, pointer xx_v(:,:)
8227       ....
8228       call MatDenseGetArrayF90(x,xx_v,ierr)
8229       a = xx_v(3)
8230       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8231 .ve
8232 
8233     Level: advanced
8234 
8235 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8236 M*/
8237 
8238 /*MC
8239     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8240     accessed with `MatDenseGetArrayF90()`.
8241 
8242     Synopsis:
8243     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8244 
8245     Not Collective
8246 
8247     Input Parameters:
8248 +   x - matrix
8249 -   xx_v - the Fortran90 pointer to the array
8250 
8251     Output Parameter:
8252 .   ierr - error code
8253 
8254     Example of Usage:
8255 .vb
8256        PetscScalar, pointer xx_v(:,:)
8257        ....
8258        call MatDenseGetArrayF90(x,xx_v,ierr)
8259        a = xx_v(3)
8260        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8261 .ve
8262 
8263     Level: advanced
8264 
8265 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8266 M*/
8267 
8268 /*MC
8269     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8270 
8271     Synopsis:
8272     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8273 
8274     Not Collective
8275 
8276     Input Parameter:
8277 .   x - matrix
8278 
8279     Output Parameters:
8280 +   xx_v - the Fortran pointer to the array
8281 -   ierr - error code
8282 
8283     Example of Usage:
8284 .vb
8285       PetscScalar, pointer xx_v(:)
8286       ....
8287       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8288       a = xx_v(3)
8289       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8290 .ve
8291 
8292     Level: advanced
8293 
8294 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8295 M*/
8296 
8297 /*MC
8298     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8299     accessed with `MatSeqAIJGetArrayF90()`.
8300 
8301     Synopsis:
8302     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8303 
8304     Not Collective
8305 
8306     Input Parameters:
8307 +   x - matrix
8308 -   xx_v - the Fortran90 pointer to the array
8309 
8310     Output Parameter:
8311 .   ierr - error code
8312 
8313     Example of Usage:
8314 .vb
8315        PetscScalar, pointer xx_v(:)
8316        ....
8317        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8318        a = xx_v(3)
8319        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8320 .ve
8321 
8322     Level: advanced
8323 
8324 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8325 M*/
8326 
8327 /*@
8328   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8329   as the original matrix.
8330 
8331   Collective
8332 
8333   Input Parameters:
8334 + mat   - the original matrix
8335 . isrow - parallel `IS` containing the rows this processor should obtain
8336 . 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.
8337 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8338 
8339   Output Parameter:
8340 . newmat - the new submatrix, of the same type as the original matrix
8341 
8342   Level: advanced
8343 
8344   Notes:
8345   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8346 
8347   Some matrix types place restrictions on the row and column indices, such
8348   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;
8349   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8350 
8351   The index sets may not have duplicate entries.
8352 
8353   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8354   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8355   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8356   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8357   you are finished using it.
8358 
8359   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8360   the input matrix.
8361 
8362   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8363 
8364   Example usage:
8365   Consider the following 8x8 matrix with 34 non-zero values, that is
8366   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8367   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8368   as follows
8369 .vb
8370             1  2  0  |  0  3  0  |  0  4
8371     Proc0   0  5  6  |  7  0  0  |  8  0
8372             9  0 10  | 11  0  0  | 12  0
8373     -------------------------------------
8374            13  0 14  | 15 16 17  |  0  0
8375     Proc1   0 18  0  | 19 20 21  |  0  0
8376             0  0  0  | 22 23  0  | 24  0
8377     -------------------------------------
8378     Proc2  25 26 27  |  0  0 28  | 29  0
8379            30  0  0  | 31 32 33  |  0 34
8380 .ve
8381 
8382   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8383 
8384 .vb
8385             2  0  |  0  3  0  |  0
8386     Proc0   5  6  |  7  0  0  |  8
8387     -------------------------------
8388     Proc1  18  0  | 19 20 21  |  0
8389     -------------------------------
8390     Proc2  26 27  |  0  0 28  | 29
8391             0  0  | 31 32 33  |  0
8392 .ve
8393 
8394 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8395 @*/
8396 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8397 {
8398   PetscMPIInt size;
8399   Mat        *local;
8400   IS          iscoltmp;
8401   PetscBool   flg;
8402 
8403   PetscFunctionBegin;
8404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8405   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8406   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8407   PetscAssertPointer(newmat, 5);
8408   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8409   PetscValidType(mat, 1);
8410   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8411   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8412 
8413   MatCheckPreallocated(mat, 1);
8414   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8415 
8416   if (!iscol || isrow == iscol) {
8417     PetscBool   stride;
8418     PetscMPIInt grabentirematrix = 0, grab;
8419     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8420     if (stride) {
8421       PetscInt first, step, n, rstart, rend;
8422       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8423       if (step == 1) {
8424         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8425         if (rstart == first) {
8426           PetscCall(ISGetLocalSize(isrow, &n));
8427           if (n == rend - rstart) grabentirematrix = 1;
8428         }
8429       }
8430     }
8431     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8432     if (grab) {
8433       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8434       if (cll == MAT_INITIAL_MATRIX) {
8435         *newmat = mat;
8436         PetscCall(PetscObjectReference((PetscObject)mat));
8437       }
8438       PetscFunctionReturn(PETSC_SUCCESS);
8439     }
8440   }
8441 
8442   if (!iscol) {
8443     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8444   } else {
8445     iscoltmp = iscol;
8446   }
8447 
8448   /* if original matrix is on just one processor then use submatrix generated */
8449   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8450     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8451     goto setproperties;
8452   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8453     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8454     *newmat = *local;
8455     PetscCall(PetscFree(local));
8456     goto setproperties;
8457   } else if (!mat->ops->createsubmatrix) {
8458     /* Create a new matrix type that implements the operation using the full matrix */
8459     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8460     switch (cll) {
8461     case MAT_INITIAL_MATRIX:
8462       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8463       break;
8464     case MAT_REUSE_MATRIX:
8465       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8466       break;
8467     default:
8468       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8469     }
8470     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8471     goto setproperties;
8472   }
8473 
8474   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8475   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8476   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8477 
8478 setproperties:
8479   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8480   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8481   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8482   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8483   PetscFunctionReturn(PETSC_SUCCESS);
8484 }
8485 
8486 /*@
8487   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8488 
8489   Not Collective
8490 
8491   Input Parameters:
8492 + A - the matrix we wish to propagate options from
8493 - B - the matrix we wish to propagate options to
8494 
8495   Level: beginner
8496 
8497   Note:
8498   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8499 
8500 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8501 @*/
8502 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8503 {
8504   PetscFunctionBegin;
8505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8506   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8507   B->symmetry_eternal            = A->symmetry_eternal;
8508   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8509   B->symmetric                   = A->symmetric;
8510   B->structurally_symmetric      = A->structurally_symmetric;
8511   B->spd                         = A->spd;
8512   B->hermitian                   = A->hermitian;
8513   PetscFunctionReturn(PETSC_SUCCESS);
8514 }
8515 
8516 /*@
8517   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8518   used during the assembly process to store values that belong to
8519   other processors.
8520 
8521   Not Collective
8522 
8523   Input Parameters:
8524 + mat   - the matrix
8525 . size  - the initial size of the stash.
8526 - bsize - the initial size of the block-stash(if used).
8527 
8528   Options Database Keys:
8529 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8530 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8531 
8532   Level: intermediate
8533 
8534   Notes:
8535   The block-stash is used for values set with `MatSetValuesBlocked()` while
8536   the stash is used for values set with `MatSetValues()`
8537 
8538   Run with the option -info and look for output of the form
8539   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8540   to determine the appropriate value, MM, to use for size and
8541   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8542   to determine the value, BMM to use for bsize
8543 
8544 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8545 @*/
8546 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8547 {
8548   PetscFunctionBegin;
8549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8550   PetscValidType(mat, 1);
8551   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8552   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8553   PetscFunctionReturn(PETSC_SUCCESS);
8554 }
8555 
8556 /*@
8557   MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8558   the matrix
8559 
8560   Neighbor-wise Collective
8561 
8562   Input Parameters:
8563 + A - the matrix
8564 . x - the vector to be multiplied by the interpolation operator
8565 - y - the vector to be added to the result
8566 
8567   Output Parameter:
8568 . w - the resulting vector
8569 
8570   Level: intermediate
8571 
8572   Notes:
8573   `w` may be the same vector as `y`.
8574 
8575   This allows one to use either the restriction or interpolation (its transpose)
8576   matrix to do the interpolation
8577 
8578 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8579 @*/
8580 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8581 {
8582   PetscInt M, N, Ny;
8583 
8584   PetscFunctionBegin;
8585   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8586   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8587   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8588   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8589   PetscCall(MatGetSize(A, &M, &N));
8590   PetscCall(VecGetSize(y, &Ny));
8591   if (M == Ny) {
8592     PetscCall(MatMultAdd(A, x, y, w));
8593   } else {
8594     PetscCall(MatMultTransposeAdd(A, x, y, w));
8595   }
8596   PetscFunctionReturn(PETSC_SUCCESS);
8597 }
8598 
8599 /*@
8600   MatInterpolate - y = A*x or A'*x depending on the shape of
8601   the matrix
8602 
8603   Neighbor-wise Collective
8604 
8605   Input Parameters:
8606 + A - the matrix
8607 - x - the vector to be interpolated
8608 
8609   Output Parameter:
8610 . y - the resulting vector
8611 
8612   Level: intermediate
8613 
8614   Note:
8615   This allows one to use either the restriction or interpolation (its transpose)
8616   matrix to do the interpolation
8617 
8618 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8619 @*/
8620 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8621 {
8622   PetscInt M, N, Ny;
8623 
8624   PetscFunctionBegin;
8625   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8626   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8627   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8628   PetscCall(MatGetSize(A, &M, &N));
8629   PetscCall(VecGetSize(y, &Ny));
8630   if (M == Ny) {
8631     PetscCall(MatMult(A, x, y));
8632   } else {
8633     PetscCall(MatMultTranspose(A, x, y));
8634   }
8635   PetscFunctionReturn(PETSC_SUCCESS);
8636 }
8637 
8638 /*@
8639   MatRestrict - y = A*x or A'*x
8640 
8641   Neighbor-wise Collective
8642 
8643   Input Parameters:
8644 + A - the matrix
8645 - x - the vector to be restricted
8646 
8647   Output Parameter:
8648 . y - the resulting vector
8649 
8650   Level: intermediate
8651 
8652   Note:
8653   This allows one to use either the restriction or interpolation (its transpose)
8654   matrix to do the restriction
8655 
8656 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8657 @*/
8658 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8659 {
8660   PetscInt M, N, Ny;
8661 
8662   PetscFunctionBegin;
8663   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8664   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8665   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8666   PetscCall(MatGetSize(A, &M, &N));
8667   PetscCall(VecGetSize(y, &Ny));
8668   if (M == Ny) {
8669     PetscCall(MatMult(A, x, y));
8670   } else {
8671     PetscCall(MatMultTranspose(A, x, y));
8672   }
8673   PetscFunctionReturn(PETSC_SUCCESS);
8674 }
8675 
8676 /*@
8677   MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8678 
8679   Neighbor-wise Collective
8680 
8681   Input Parameters:
8682 + A - the matrix
8683 . x - the input dense matrix to be multiplied
8684 - w - the input dense matrix to be added to the result
8685 
8686   Output Parameter:
8687 . y - the output dense matrix
8688 
8689   Level: intermediate
8690 
8691   Note:
8692   This allows one to use either the restriction or interpolation (its transpose)
8693   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8694   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8695 
8696 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8697 @*/
8698 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8699 {
8700   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8701   PetscBool trans = PETSC_TRUE;
8702   MatReuse  reuse = MAT_INITIAL_MATRIX;
8703 
8704   PetscFunctionBegin;
8705   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8706   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8707   PetscValidType(x, 2);
8708   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8709   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8710   PetscCall(MatGetSize(A, &M, &N));
8711   PetscCall(MatGetSize(x, &Mx, &Nx));
8712   if (N == Mx) trans = PETSC_FALSE;
8713   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);
8714   Mo = trans ? N : M;
8715   if (*y) {
8716     PetscCall(MatGetSize(*y, &My, &Ny));
8717     if (Mo == My && Nx == Ny) {
8718       reuse = MAT_REUSE_MATRIX;
8719     } else {
8720       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);
8721       PetscCall(MatDestroy(y));
8722     }
8723   }
8724 
8725   if (w && *y == w) { /* this is to minimize changes in PCMG */
8726     PetscBool flg;
8727 
8728     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8729     if (w) {
8730       PetscInt My, Ny, Mw, Nw;
8731 
8732       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8733       PetscCall(MatGetSize(*y, &My, &Ny));
8734       PetscCall(MatGetSize(w, &Mw, &Nw));
8735       if (!flg || My != Mw || Ny != Nw) w = NULL;
8736     }
8737     if (!w) {
8738       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8739       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8740       PetscCall(PetscObjectDereference((PetscObject)w));
8741     } else {
8742       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8743     }
8744   }
8745   if (!trans) {
8746     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8747   } else {
8748     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8749   }
8750   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8751   PetscFunctionReturn(PETSC_SUCCESS);
8752 }
8753 
8754 /*@
8755   MatMatInterpolate - Y = A*X or A'*X
8756 
8757   Neighbor-wise Collective
8758 
8759   Input Parameters:
8760 + A - the matrix
8761 - x - the input dense matrix
8762 
8763   Output Parameter:
8764 . y - the output dense matrix
8765 
8766   Level: intermediate
8767 
8768   Note:
8769   This allows one to use either the restriction or interpolation (its transpose)
8770   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8771   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8772 
8773 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8774 @*/
8775 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8776 {
8777   PetscFunctionBegin;
8778   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8779   PetscFunctionReturn(PETSC_SUCCESS);
8780 }
8781 
8782 /*@
8783   MatMatRestrict - Y = A*X or A'*X
8784 
8785   Neighbor-wise Collective
8786 
8787   Input Parameters:
8788 + A - the matrix
8789 - x - the input dense matrix
8790 
8791   Output Parameter:
8792 . y - the output dense matrix
8793 
8794   Level: intermediate
8795 
8796   Note:
8797   This allows one to use either the restriction or interpolation (its transpose)
8798   matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8799   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8800 
8801 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8802 @*/
8803 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8804 {
8805   PetscFunctionBegin;
8806   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8807   PetscFunctionReturn(PETSC_SUCCESS);
8808 }
8809 
8810 /*@
8811   MatGetNullSpace - retrieves the null space of a matrix.
8812 
8813   Logically Collective
8814 
8815   Input Parameters:
8816 + mat    - the matrix
8817 - nullsp - the null space object
8818 
8819   Level: developer
8820 
8821 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8822 @*/
8823 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8824 {
8825   PetscFunctionBegin;
8826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8827   PetscAssertPointer(nullsp, 2);
8828   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8829   PetscFunctionReturn(PETSC_SUCCESS);
8830 }
8831 
8832 /*@
8833   MatSetNullSpace - attaches a null space to a matrix.
8834 
8835   Logically Collective
8836 
8837   Input Parameters:
8838 + mat    - the matrix
8839 - nullsp - the null space object
8840 
8841   Level: advanced
8842 
8843   Notes:
8844   This null space is used by the `KSP` linear solvers to solve singular systems.
8845 
8846   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`
8847 
8848   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
8849   to zero but the linear system will still be solved in a least squares sense.
8850 
8851   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8852   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).
8853   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
8854   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
8855   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).
8856   This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8857 
8858   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8859   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8860   routine also automatically calls `MatSetTransposeNullSpace()`.
8861 
8862   The user should call `MatNullSpaceDestroy()`.
8863 
8864 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8865           `KSPSetPCSide()`
8866 @*/
8867 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8868 {
8869   PetscFunctionBegin;
8870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8871   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8872   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8873   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8874   mat->nullsp = nullsp;
8875   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8876   PetscFunctionReturn(PETSC_SUCCESS);
8877 }
8878 
8879 /*@
8880   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8881 
8882   Logically Collective
8883 
8884   Input Parameters:
8885 + mat    - the matrix
8886 - nullsp - the null space object
8887 
8888   Level: developer
8889 
8890 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8891 @*/
8892 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8893 {
8894   PetscFunctionBegin;
8895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8896   PetscValidType(mat, 1);
8897   PetscAssertPointer(nullsp, 2);
8898   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8899   PetscFunctionReturn(PETSC_SUCCESS);
8900 }
8901 
8902 /*@
8903   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8904 
8905   Logically Collective
8906 
8907   Input Parameters:
8908 + mat    - the matrix
8909 - nullsp - the null space object
8910 
8911   Level: advanced
8912 
8913   Notes:
8914   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8915 
8916   See `MatSetNullSpace()`
8917 
8918 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8919 @*/
8920 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8921 {
8922   PetscFunctionBegin;
8923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8924   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8925   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8926   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8927   mat->transnullsp = nullsp;
8928   PetscFunctionReturn(PETSC_SUCCESS);
8929 }
8930 
8931 /*@
8932   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8933   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8934 
8935   Logically Collective
8936 
8937   Input Parameters:
8938 + mat    - the matrix
8939 - nullsp - the null space object
8940 
8941   Level: advanced
8942 
8943   Notes:
8944   Overwrites any previous near null space that may have been attached
8945 
8946   You can remove the null space by calling this routine with an nullsp of `NULL`
8947 
8948 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8949 @*/
8950 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8951 {
8952   PetscFunctionBegin;
8953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8954   PetscValidType(mat, 1);
8955   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8956   MatCheckPreallocated(mat, 1);
8957   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8958   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8959   mat->nearnullsp = nullsp;
8960   PetscFunctionReturn(PETSC_SUCCESS);
8961 }
8962 
8963 /*@
8964   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8965 
8966   Not Collective
8967 
8968   Input Parameter:
8969 . mat - the matrix
8970 
8971   Output Parameter:
8972 . nullsp - the null space object, `NULL` if not set
8973 
8974   Level: advanced
8975 
8976 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8977 @*/
8978 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8979 {
8980   PetscFunctionBegin;
8981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8982   PetscValidType(mat, 1);
8983   PetscAssertPointer(nullsp, 2);
8984   MatCheckPreallocated(mat, 1);
8985   *nullsp = mat->nearnullsp;
8986   PetscFunctionReturn(PETSC_SUCCESS);
8987 }
8988 
8989 /*@C
8990   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8991 
8992   Collective
8993 
8994   Input Parameters:
8995 + mat  - the matrix
8996 . row  - row/column permutation
8997 - info - information on desired factorization process
8998 
8999   Level: developer
9000 
9001   Notes:
9002   Probably really in-place only when level of fill is zero, otherwise allocates
9003   new space to store factored matrix and deletes previous memory.
9004 
9005   Most users should employ the `KSP` interface for linear solvers
9006   instead of working directly with matrix algebra routines such as this.
9007   See, e.g., `KSPCreate()`.
9008 
9009   Developer Notes:
9010   The Fortran interface is not autogenerated as the
9011   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9012 
9013 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9014 @*/
9015 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9016 {
9017   PetscFunctionBegin;
9018   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9019   PetscValidType(mat, 1);
9020   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9021   PetscAssertPointer(info, 3);
9022   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9023   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9024   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9025   MatCheckPreallocated(mat, 1);
9026   PetscUseTypeMethod(mat, iccfactor, row, info);
9027   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9028   PetscFunctionReturn(PETSC_SUCCESS);
9029 }
9030 
9031 /*@
9032   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9033   ghosted ones.
9034 
9035   Not Collective
9036 
9037   Input Parameters:
9038 + mat  - the matrix
9039 - diag - the diagonal values, including ghost ones
9040 
9041   Level: developer
9042 
9043   Notes:
9044   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9045 
9046   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9047 
9048 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9049 @*/
9050 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9051 {
9052   PetscMPIInt size;
9053 
9054   PetscFunctionBegin;
9055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9056   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9057   PetscValidType(mat, 1);
9058 
9059   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9060   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9061   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9062   if (size == 1) {
9063     PetscInt n, m;
9064     PetscCall(VecGetSize(diag, &n));
9065     PetscCall(MatGetSize(mat, NULL, &m));
9066     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9067     PetscCall(MatDiagonalScale(mat, NULL, diag));
9068   } else {
9069     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9070   }
9071   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9072   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9073   PetscFunctionReturn(PETSC_SUCCESS);
9074 }
9075 
9076 /*@
9077   MatGetInertia - Gets the inertia from a factored matrix
9078 
9079   Collective
9080 
9081   Input Parameter:
9082 . mat - the matrix
9083 
9084   Output Parameters:
9085 + nneg  - number of negative eigenvalues
9086 . nzero - number of zero eigenvalues
9087 - npos  - number of positive eigenvalues
9088 
9089   Level: advanced
9090 
9091   Note:
9092   Matrix must have been factored by `MatCholeskyFactor()`
9093 
9094 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9095 @*/
9096 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9097 {
9098   PetscFunctionBegin;
9099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9100   PetscValidType(mat, 1);
9101   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9103   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9104   PetscFunctionReturn(PETSC_SUCCESS);
9105 }
9106 
9107 /*@C
9108   MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9109 
9110   Neighbor-wise Collective
9111 
9112   Input Parameters:
9113 + mat - the factored matrix obtained with `MatGetFactor()`
9114 - b   - the right-hand-side vectors
9115 
9116   Output Parameter:
9117 . x - the result vectors
9118 
9119   Level: developer
9120 
9121   Note:
9122   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9123   call `MatSolves`(A,x,x).
9124 
9125 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9126 @*/
9127 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9128 {
9129   PetscFunctionBegin;
9130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9131   PetscValidType(mat, 1);
9132   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9133   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9134   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9135 
9136   MatCheckPreallocated(mat, 1);
9137   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9138   PetscUseTypeMethod(mat, solves, b, x);
9139   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9140   PetscFunctionReturn(PETSC_SUCCESS);
9141 }
9142 
9143 /*@
9144   MatIsSymmetric - Test whether a matrix is symmetric
9145 
9146   Collective
9147 
9148   Input Parameters:
9149 + A   - the matrix to test
9150 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9151 
9152   Output Parameter:
9153 . flg - the result
9154 
9155   Level: intermediate
9156 
9157   Notes:
9158   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9159 
9160   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9161 
9162   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9163   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9164 
9165 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9166           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9167 @*/
9168 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9169 {
9170   PetscFunctionBegin;
9171   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9172   PetscAssertPointer(flg, 3);
9173 
9174   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9175   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9176   else {
9177     PetscUseTypeMethod(A, issymmetric, tol, flg);
9178     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9179   }
9180   PetscFunctionReturn(PETSC_SUCCESS);
9181 }
9182 
9183 /*@
9184   MatIsHermitian - Test whether a matrix is Hermitian
9185 
9186   Collective
9187 
9188   Input Parameters:
9189 + A   - the matrix to test
9190 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9191 
9192   Output Parameter:
9193 . flg - the result
9194 
9195   Level: intermediate
9196 
9197   Notes:
9198   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9199 
9200   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9201 
9202   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9203   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9204 
9205 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9206           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9207 @*/
9208 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9209 {
9210   PetscFunctionBegin;
9211   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9212   PetscAssertPointer(flg, 3);
9213 
9214   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9215   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9216   else {
9217     PetscUseTypeMethod(A, ishermitian, tol, flg);
9218     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9219   }
9220   PetscFunctionReturn(PETSC_SUCCESS);
9221 }
9222 
9223 /*@
9224   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9225 
9226   Not Collective
9227 
9228   Input Parameter:
9229 . A - the matrix to check
9230 
9231   Output Parameters:
9232 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9233 - flg - the result (only valid if set is `PETSC_TRUE`)
9234 
9235   Level: advanced
9236 
9237   Notes:
9238   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9239   if you want it explicitly checked
9240 
9241   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9242   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9243 
9244 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9245 @*/
9246 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9247 {
9248   PetscFunctionBegin;
9249   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9250   PetscAssertPointer(set, 2);
9251   PetscAssertPointer(flg, 3);
9252   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9253     *set = PETSC_TRUE;
9254     *flg = PetscBool3ToBool(A->symmetric);
9255   } else {
9256     *set = PETSC_FALSE;
9257   }
9258   PetscFunctionReturn(PETSC_SUCCESS);
9259 }
9260 
9261 /*@
9262   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9263 
9264   Not Collective
9265 
9266   Input Parameter:
9267 . A - the matrix to check
9268 
9269   Output Parameters:
9270 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9271 - flg - the result (only valid if set is `PETSC_TRUE`)
9272 
9273   Level: advanced
9274 
9275   Notes:
9276   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9277 
9278   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9279   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9280 
9281 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9282 @*/
9283 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9284 {
9285   PetscFunctionBegin;
9286   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9287   PetscAssertPointer(set, 2);
9288   PetscAssertPointer(flg, 3);
9289   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9290     *set = PETSC_TRUE;
9291     *flg = PetscBool3ToBool(A->spd);
9292   } else {
9293     *set = PETSC_FALSE;
9294   }
9295   PetscFunctionReturn(PETSC_SUCCESS);
9296 }
9297 
9298 /*@
9299   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9300 
9301   Not Collective
9302 
9303   Input Parameter:
9304 . A - the matrix to check
9305 
9306   Output Parameters:
9307 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9308 - flg - the result (only valid if set is `PETSC_TRUE`)
9309 
9310   Level: advanced
9311 
9312   Notes:
9313   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9314   if you want it explicitly checked
9315 
9316   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9317   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9318 
9319 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9320 @*/
9321 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9322 {
9323   PetscFunctionBegin;
9324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9325   PetscAssertPointer(set, 2);
9326   PetscAssertPointer(flg, 3);
9327   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9328     *set = PETSC_TRUE;
9329     *flg = PetscBool3ToBool(A->hermitian);
9330   } else {
9331     *set = PETSC_FALSE;
9332   }
9333   PetscFunctionReturn(PETSC_SUCCESS);
9334 }
9335 
9336 /*@
9337   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9338 
9339   Collective
9340 
9341   Input Parameter:
9342 . A - the matrix to test
9343 
9344   Output Parameter:
9345 . flg - the result
9346 
9347   Level: intermediate
9348 
9349   Notes:
9350   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9351 
9352   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
9353   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9354 
9355 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9356 @*/
9357 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9358 {
9359   PetscFunctionBegin;
9360   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9361   PetscAssertPointer(flg, 2);
9362   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9363     *flg = PetscBool3ToBool(A->structurally_symmetric);
9364   } else {
9365     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9366     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9367   }
9368   PetscFunctionReturn(PETSC_SUCCESS);
9369 }
9370 
9371 /*@
9372   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9373 
9374   Not Collective
9375 
9376   Input Parameter:
9377 . A - the matrix to check
9378 
9379   Output Parameters:
9380 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9381 - flg - the result (only valid if set is PETSC_TRUE)
9382 
9383   Level: advanced
9384 
9385   Notes:
9386   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
9387   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9388 
9389   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9390 
9391 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9392 @*/
9393 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9394 {
9395   PetscFunctionBegin;
9396   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9397   PetscAssertPointer(set, 2);
9398   PetscAssertPointer(flg, 3);
9399   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9400     *set = PETSC_TRUE;
9401     *flg = PetscBool3ToBool(A->structurally_symmetric);
9402   } else {
9403     *set = PETSC_FALSE;
9404   }
9405   PetscFunctionReturn(PETSC_SUCCESS);
9406 }
9407 
9408 /*@
9409   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9410   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9411 
9412   Not Collective
9413 
9414   Input Parameter:
9415 . mat - the matrix
9416 
9417   Output Parameters:
9418 + nstash    - the size of the stash
9419 . reallocs  - the number of additional mallocs incurred.
9420 . bnstash   - the size of the block stash
9421 - breallocs - the number of additional mallocs incurred.in the block stash
9422 
9423   Level: advanced
9424 
9425 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9426 @*/
9427 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9428 {
9429   PetscFunctionBegin;
9430   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9431   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9432   PetscFunctionReturn(PETSC_SUCCESS);
9433 }
9434 
9435 /*@C
9436   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9437   parallel layout, `PetscLayout` for rows and columns
9438 
9439   Collective
9440 
9441   Input Parameter:
9442 . mat - the matrix
9443 
9444   Output Parameters:
9445 + right - (optional) vector that the matrix can be multiplied against
9446 - left  - (optional) vector that the matrix vector product can be stored in
9447 
9448   Level: advanced
9449 
9450   Notes:
9451   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()`.
9452 
9453   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9454 
9455 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9456 @*/
9457 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9458 {
9459   PetscFunctionBegin;
9460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9461   PetscValidType(mat, 1);
9462   if (mat->ops->getvecs) {
9463     PetscUseTypeMethod(mat, getvecs, right, left);
9464   } else {
9465     if (right) {
9466       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9467       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9468       PetscCall(VecSetType(*right, mat->defaultvectype));
9469 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9470       if (mat->boundtocpu && mat->bindingpropagates) {
9471         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9472         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9473       }
9474 #endif
9475     }
9476     if (left) {
9477       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9478       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9479       PetscCall(VecSetType(*left, mat->defaultvectype));
9480 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9481       if (mat->boundtocpu && mat->bindingpropagates) {
9482         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9483         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9484       }
9485 #endif
9486     }
9487   }
9488   PetscFunctionReturn(PETSC_SUCCESS);
9489 }
9490 
9491 /*@C
9492   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9493   with default values.
9494 
9495   Not Collective
9496 
9497   Input Parameter:
9498 . info - the `MatFactorInfo` data structure
9499 
9500   Level: developer
9501 
9502   Notes:
9503   The solvers are generally used through the `KSP` and `PC` objects, for example
9504   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9505 
9506   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9507 
9508   Developer Notes:
9509   The Fortran interface is not autogenerated as the
9510   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9511 
9512 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9513 @*/
9514 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9515 {
9516   PetscFunctionBegin;
9517   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9518   PetscFunctionReturn(PETSC_SUCCESS);
9519 }
9520 
9521 /*@
9522   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9523 
9524   Collective
9525 
9526   Input Parameters:
9527 + mat - the factored matrix
9528 - is  - the index set defining the Schur indices (0-based)
9529 
9530   Level: advanced
9531 
9532   Notes:
9533   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9534 
9535   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9536 
9537   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9538 
9539 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9540           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9541 @*/
9542 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9543 {
9544   PetscErrorCode (*f)(Mat, IS);
9545 
9546   PetscFunctionBegin;
9547   PetscValidType(mat, 1);
9548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9549   PetscValidType(is, 2);
9550   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9551   PetscCheckSameComm(mat, 1, is, 2);
9552   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9553   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9554   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9555   PetscCall(MatDestroy(&mat->schur));
9556   PetscCall((*f)(mat, is));
9557   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9558   PetscFunctionReturn(PETSC_SUCCESS);
9559 }
9560 
9561 /*@
9562   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9563 
9564   Logically Collective
9565 
9566   Input Parameters:
9567 + F      - the factored matrix obtained by calling `MatGetFactor()`
9568 . S      - location where to return the Schur complement, can be `NULL`
9569 - status - the status of the Schur complement matrix, can be `NULL`
9570 
9571   Level: advanced
9572 
9573   Notes:
9574   You must call `MatFactorSetSchurIS()` before calling this routine.
9575 
9576   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9577 
9578   The routine provides a copy of the Schur matrix stored within the solver data structures.
9579   The caller must destroy the object when it is no longer needed.
9580   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9581 
9582   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)
9583 
9584   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9585 
9586   Developer Notes:
9587   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9588   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9589 
9590 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9591 @*/
9592 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9593 {
9594   PetscFunctionBegin;
9595   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9596   if (S) PetscAssertPointer(S, 2);
9597   if (status) PetscAssertPointer(status, 3);
9598   if (S) {
9599     PetscErrorCode (*f)(Mat, Mat *);
9600 
9601     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9602     if (f) {
9603       PetscCall((*f)(F, S));
9604     } else {
9605       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9606     }
9607   }
9608   if (status) *status = F->schur_status;
9609   PetscFunctionReturn(PETSC_SUCCESS);
9610 }
9611 
9612 /*@
9613   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9614 
9615   Logically Collective
9616 
9617   Input Parameters:
9618 + F      - the factored matrix obtained by calling `MatGetFactor()`
9619 . S      - location where to return the Schur complement, can be `NULL`
9620 - status - the status of the Schur complement matrix, can be `NULL`
9621 
9622   Level: advanced
9623 
9624   Notes:
9625   You must call `MatFactorSetSchurIS()` before calling this routine.
9626 
9627   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9628 
9629   The routine returns a the Schur Complement stored within the data structures of the solver.
9630 
9631   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9632 
9633   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9634 
9635   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9636 
9637   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9638 
9639 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9640 @*/
9641 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9642 {
9643   PetscFunctionBegin;
9644   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9645   if (S) PetscAssertPointer(S, 2);
9646   if (status) PetscAssertPointer(status, 3);
9647   if (S) *S = F->schur;
9648   if (status) *status = F->schur_status;
9649   PetscFunctionReturn(PETSC_SUCCESS);
9650 }
9651 
9652 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9653 {
9654   Mat S = F->schur;
9655 
9656   PetscFunctionBegin;
9657   switch (F->schur_status) {
9658   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9659   case MAT_FACTOR_SCHUR_INVERTED:
9660     if (S) {
9661       S->ops->solve             = NULL;
9662       S->ops->matsolve          = NULL;
9663       S->ops->solvetranspose    = NULL;
9664       S->ops->matsolvetranspose = NULL;
9665       S->ops->solveadd          = NULL;
9666       S->ops->solvetransposeadd = NULL;
9667       S->factortype             = MAT_FACTOR_NONE;
9668       PetscCall(PetscFree(S->solvertype));
9669     }
9670   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9671     break;
9672   default:
9673     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9674   }
9675   PetscFunctionReturn(PETSC_SUCCESS);
9676 }
9677 
9678 /*@
9679   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9680 
9681   Logically Collective
9682 
9683   Input Parameters:
9684 + F      - the factored matrix obtained by calling `MatGetFactor()`
9685 . S      - location where the Schur complement is stored
9686 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9687 
9688   Level: advanced
9689 
9690 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9691 @*/
9692 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9693 {
9694   PetscFunctionBegin;
9695   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9696   if (S) {
9697     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9698     *S = NULL;
9699   }
9700   F->schur_status = status;
9701   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9702   PetscFunctionReturn(PETSC_SUCCESS);
9703 }
9704 
9705 /*@
9706   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9707 
9708   Logically Collective
9709 
9710   Input Parameters:
9711 + F   - the factored matrix obtained by calling `MatGetFactor()`
9712 . rhs - location where the right hand side of the Schur complement system is stored
9713 - sol - location where the solution of the Schur complement system has to be returned
9714 
9715   Level: advanced
9716 
9717   Notes:
9718   The sizes of the vectors should match the size of the Schur complement
9719 
9720   Must be called after `MatFactorSetSchurIS()`
9721 
9722 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9723 @*/
9724 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9725 {
9726   PetscFunctionBegin;
9727   PetscValidType(F, 1);
9728   PetscValidType(rhs, 2);
9729   PetscValidType(sol, 3);
9730   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9731   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9732   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9733   PetscCheckSameComm(F, 1, rhs, 2);
9734   PetscCheckSameComm(F, 1, sol, 3);
9735   PetscCall(MatFactorFactorizeSchurComplement(F));
9736   switch (F->schur_status) {
9737   case MAT_FACTOR_SCHUR_FACTORED:
9738     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9739     break;
9740   case MAT_FACTOR_SCHUR_INVERTED:
9741     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9742     break;
9743   default:
9744     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9745   }
9746   PetscFunctionReturn(PETSC_SUCCESS);
9747 }
9748 
9749 /*@
9750   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9751 
9752   Logically Collective
9753 
9754   Input Parameters:
9755 + F   - the factored matrix obtained by calling `MatGetFactor()`
9756 . rhs - location where the right hand side of the Schur complement system is stored
9757 - sol - location where the solution of the Schur complement system has to be returned
9758 
9759   Level: advanced
9760 
9761   Notes:
9762   The sizes of the vectors should match the size of the Schur complement
9763 
9764   Must be called after `MatFactorSetSchurIS()`
9765 
9766 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9767 @*/
9768 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9769 {
9770   PetscFunctionBegin;
9771   PetscValidType(F, 1);
9772   PetscValidType(rhs, 2);
9773   PetscValidType(sol, 3);
9774   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9775   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9776   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9777   PetscCheckSameComm(F, 1, rhs, 2);
9778   PetscCheckSameComm(F, 1, sol, 3);
9779   PetscCall(MatFactorFactorizeSchurComplement(F));
9780   switch (F->schur_status) {
9781   case MAT_FACTOR_SCHUR_FACTORED:
9782     PetscCall(MatSolve(F->schur, rhs, sol));
9783     break;
9784   case MAT_FACTOR_SCHUR_INVERTED:
9785     PetscCall(MatMult(F->schur, rhs, sol));
9786     break;
9787   default:
9788     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9789   }
9790   PetscFunctionReturn(PETSC_SUCCESS);
9791 }
9792 
9793 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9794 #if PetscDefined(HAVE_CUDA)
9795 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9796 #endif
9797 
9798 /* Schur status updated in the interface */
9799 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9800 {
9801   Mat S = F->schur;
9802 
9803   PetscFunctionBegin;
9804   if (S) {
9805     PetscMPIInt size;
9806     PetscBool   isdense, isdensecuda;
9807 
9808     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9809     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9810     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9811     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9812     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9813     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9814     if (isdense) {
9815       PetscCall(MatSeqDenseInvertFactors_Private(S));
9816     } else if (isdensecuda) {
9817 #if defined(PETSC_HAVE_CUDA)
9818       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9819 #endif
9820     }
9821     // HIP??????????????
9822     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9823   }
9824   PetscFunctionReturn(PETSC_SUCCESS);
9825 }
9826 
9827 /*@
9828   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9829 
9830   Logically Collective
9831 
9832   Input Parameter:
9833 . F - the factored matrix obtained by calling `MatGetFactor()`
9834 
9835   Level: advanced
9836 
9837   Notes:
9838   Must be called after `MatFactorSetSchurIS()`.
9839 
9840   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9841 
9842 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9843 @*/
9844 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9845 {
9846   PetscFunctionBegin;
9847   PetscValidType(F, 1);
9848   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9849   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9850   PetscCall(MatFactorFactorizeSchurComplement(F));
9851   PetscCall(MatFactorInvertSchurComplement_Private(F));
9852   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9853   PetscFunctionReturn(PETSC_SUCCESS);
9854 }
9855 
9856 /*@
9857   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9858 
9859   Logically Collective
9860 
9861   Input Parameter:
9862 . F - the factored matrix obtained by calling `MatGetFactor()`
9863 
9864   Level: advanced
9865 
9866   Note:
9867   Must be called after `MatFactorSetSchurIS()`
9868 
9869 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9870 @*/
9871 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9872 {
9873   MatFactorInfo info;
9874 
9875   PetscFunctionBegin;
9876   PetscValidType(F, 1);
9877   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9878   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9879   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9880   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9881   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9882     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9883   } else {
9884     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9885   }
9886   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9887   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9888   PetscFunctionReturn(PETSC_SUCCESS);
9889 }
9890 
9891 /*@
9892   MatPtAP - Creates the matrix product C = P^T * A * P
9893 
9894   Neighbor-wise Collective
9895 
9896   Input Parameters:
9897 + A     - the matrix
9898 . P     - the projection matrix
9899 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9900 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9901           if the result is a dense matrix this is irrelevant
9902 
9903   Output Parameter:
9904 . C - the product matrix
9905 
9906   Level: intermediate
9907 
9908   Notes:
9909   C will be created and must be destroyed by the user with `MatDestroy()`.
9910 
9911   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9912 
9913   Developer Notes:
9914   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9915 
9916 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9917 @*/
9918 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9919 {
9920   PetscFunctionBegin;
9921   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9922   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9923 
9924   if (scall == MAT_INITIAL_MATRIX) {
9925     PetscCall(MatProductCreate(A, P, NULL, C));
9926     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9927     PetscCall(MatProductSetAlgorithm(*C, "default"));
9928     PetscCall(MatProductSetFill(*C, fill));
9929 
9930     (*C)->product->api_user = PETSC_TRUE;
9931     PetscCall(MatProductSetFromOptions(*C));
9932     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);
9933     PetscCall(MatProductSymbolic(*C));
9934   } else { /* scall == MAT_REUSE_MATRIX */
9935     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9936   }
9937 
9938   PetscCall(MatProductNumeric(*C));
9939   (*C)->symmetric = A->symmetric;
9940   (*C)->spd       = A->spd;
9941   PetscFunctionReturn(PETSC_SUCCESS);
9942 }
9943 
9944 /*@
9945   MatRARt - Creates the matrix product C = R * A * R^T
9946 
9947   Neighbor-wise Collective
9948 
9949   Input Parameters:
9950 + A     - the matrix
9951 . R     - the projection matrix
9952 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9953 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9954           if the result is a dense matrix this is irrelevant
9955 
9956   Output Parameter:
9957 . C - the product matrix
9958 
9959   Level: intermediate
9960 
9961   Notes:
9962   C will be created and must be destroyed by the user with `MatDestroy()`.
9963 
9964   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9965 
9966   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9967   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9968   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9969   We recommend using MatPtAP().
9970 
9971 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9972 @*/
9973 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9974 {
9975   PetscFunctionBegin;
9976   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9977   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9978 
9979   if (scall == MAT_INITIAL_MATRIX) {
9980     PetscCall(MatProductCreate(A, R, NULL, C));
9981     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9982     PetscCall(MatProductSetAlgorithm(*C, "default"));
9983     PetscCall(MatProductSetFill(*C, fill));
9984 
9985     (*C)->product->api_user = PETSC_TRUE;
9986     PetscCall(MatProductSetFromOptions(*C));
9987     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);
9988     PetscCall(MatProductSymbolic(*C));
9989   } else { /* scall == MAT_REUSE_MATRIX */
9990     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9991   }
9992 
9993   PetscCall(MatProductNumeric(*C));
9994   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9995   PetscFunctionReturn(PETSC_SUCCESS);
9996 }
9997 
9998 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9999 {
10000   PetscFunctionBegin;
10001   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10002 
10003   if (scall == MAT_INITIAL_MATRIX) {
10004     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10005     PetscCall(MatProductCreate(A, B, NULL, C));
10006     PetscCall(MatProductSetType(*C, ptype));
10007     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10008     PetscCall(MatProductSetFill(*C, fill));
10009 
10010     (*C)->product->api_user = PETSC_TRUE;
10011     PetscCall(MatProductSetFromOptions(*C));
10012     PetscCall(MatProductSymbolic(*C));
10013   } else { /* scall == MAT_REUSE_MATRIX */
10014     Mat_Product *product = (*C)->product;
10015     PetscBool    isdense;
10016 
10017     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10018     if (isdense && product && product->type != ptype) {
10019       PetscCall(MatProductClear(*C));
10020       product = NULL;
10021     }
10022     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10023     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10024       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10025       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10026       product           = (*C)->product;
10027       product->fill     = fill;
10028       product->api_user = PETSC_TRUE;
10029       product->clear    = PETSC_TRUE;
10030 
10031       PetscCall(MatProductSetType(*C, ptype));
10032       PetscCall(MatProductSetFromOptions(*C));
10033       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);
10034       PetscCall(MatProductSymbolic(*C));
10035     } else { /* user may change input matrices A or B when REUSE */
10036       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10037     }
10038   }
10039   PetscCall(MatProductNumeric(*C));
10040   PetscFunctionReturn(PETSC_SUCCESS);
10041 }
10042 
10043 /*@
10044   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10045 
10046   Neighbor-wise Collective
10047 
10048   Input Parameters:
10049 + A     - the left matrix
10050 . B     - the right matrix
10051 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10052 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10053           if the result is a dense matrix this is irrelevant
10054 
10055   Output Parameter:
10056 . C - the product matrix
10057 
10058   Notes:
10059   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10060 
10061   `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
10062   call to this function with `MAT_INITIAL_MATRIX`.
10063 
10064   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10065 
10066   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`,
10067   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10068 
10069   Example of Usage:
10070 .vb
10071      MatProductCreate(A,B,NULL,&C);
10072      MatProductSetType(C,MATPRODUCT_AB);
10073      MatProductSymbolic(C);
10074      MatProductNumeric(C); // compute C=A * B
10075      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10076      MatProductNumeric(C);
10077      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10078      MatProductNumeric(C);
10079 .ve
10080 
10081   Level: intermediate
10082 
10083 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10084 @*/
10085 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10086 {
10087   PetscFunctionBegin;
10088   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10089   PetscFunctionReturn(PETSC_SUCCESS);
10090 }
10091 
10092 /*@
10093   MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10094 
10095   Neighbor-wise Collective
10096 
10097   Input Parameters:
10098 + A     - the left matrix
10099 . B     - the right matrix
10100 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10101 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10102 
10103   Output Parameter:
10104 . C - the product matrix
10105 
10106   Level: intermediate
10107 
10108   Notes:
10109   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10110 
10111   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10112 
10113   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10114   actually needed.
10115 
10116   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10117   and for pairs of `MATMPIDENSE` matrices.
10118 
10119   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10120 
10121   Options Database Keys:
10122 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10123               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10124               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10125 
10126 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10127 @*/
10128 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10129 {
10130   PetscFunctionBegin;
10131   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10132   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10133   PetscFunctionReturn(PETSC_SUCCESS);
10134 }
10135 
10136 /*@
10137   MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10138 
10139   Neighbor-wise Collective
10140 
10141   Input Parameters:
10142 + A     - the left matrix
10143 . B     - the right matrix
10144 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10145 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10146 
10147   Output Parameter:
10148 . C - the product matrix
10149 
10150   Level: intermediate
10151 
10152   Notes:
10153   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10154 
10155   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10156 
10157   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10158 
10159   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10160   actually needed.
10161 
10162   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10163   which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10164 
10165 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10166 @*/
10167 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10168 {
10169   PetscFunctionBegin;
10170   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10171   PetscFunctionReturn(PETSC_SUCCESS);
10172 }
10173 
10174 /*@
10175   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10176 
10177   Neighbor-wise Collective
10178 
10179   Input Parameters:
10180 + A     - the left matrix
10181 . B     - the middle matrix
10182 . C     - the right matrix
10183 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10184 - 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
10185           if the result is a dense matrix this is irrelevant
10186 
10187   Output Parameter:
10188 . D - the product matrix
10189 
10190   Level: intermediate
10191 
10192   Notes:
10193   Unless scall is `MAT_REUSE_MATRIX` D will be created.
10194 
10195   `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10196 
10197   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10198 
10199   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10200   actually needed.
10201 
10202   If you have many matrices with the same non-zero structure to multiply, you
10203   should use `MAT_REUSE_MATRIX` in all calls but the first
10204 
10205 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10206 @*/
10207 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10208 {
10209   PetscFunctionBegin;
10210   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10211   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10212 
10213   if (scall == MAT_INITIAL_MATRIX) {
10214     PetscCall(MatProductCreate(A, B, C, D));
10215     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10216     PetscCall(MatProductSetAlgorithm(*D, "default"));
10217     PetscCall(MatProductSetFill(*D, fill));
10218 
10219     (*D)->product->api_user = PETSC_TRUE;
10220     PetscCall(MatProductSetFromOptions(*D));
10221     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,
10222                ((PetscObject)C)->type_name);
10223     PetscCall(MatProductSymbolic(*D));
10224   } else { /* user may change input matrices when REUSE */
10225     PetscCall(MatProductReplaceMats(A, B, C, *D));
10226   }
10227   PetscCall(MatProductNumeric(*D));
10228   PetscFunctionReturn(PETSC_SUCCESS);
10229 }
10230 
10231 /*@
10232   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10233 
10234   Collective
10235 
10236   Input Parameters:
10237 + mat      - the matrix
10238 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10239 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10240 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10241 
10242   Output Parameter:
10243 . matredundant - redundant matrix
10244 
10245   Level: advanced
10246 
10247   Notes:
10248   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10249   original matrix has not changed from that last call to MatCreateRedundantMatrix().
10250 
10251   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10252   calling it.
10253 
10254   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10255 
10256 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10257 @*/
10258 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10259 {
10260   MPI_Comm       comm;
10261   PetscMPIInt    size;
10262   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10263   Mat_Redundant *redund     = NULL;
10264   PetscSubcomm   psubcomm   = NULL;
10265   MPI_Comm       subcomm_in = subcomm;
10266   Mat           *matseq;
10267   IS             isrow, iscol;
10268   PetscBool      newsubcomm = PETSC_FALSE;
10269 
10270   PetscFunctionBegin;
10271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10272   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10273     PetscAssertPointer(*matredundant, 5);
10274     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10275   }
10276 
10277   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10278   if (size == 1 || nsubcomm == 1) {
10279     if (reuse == MAT_INITIAL_MATRIX) {
10280       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10281     } else {
10282       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");
10283       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10284     }
10285     PetscFunctionReturn(PETSC_SUCCESS);
10286   }
10287 
10288   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10289   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10290   MatCheckPreallocated(mat, 1);
10291 
10292   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10293   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10294     /* create psubcomm, then get subcomm */
10295     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10296     PetscCallMPI(MPI_Comm_size(comm, &size));
10297     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10298 
10299     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10300     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10301     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10302     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10303     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10304     newsubcomm = PETSC_TRUE;
10305     PetscCall(PetscSubcommDestroy(&psubcomm));
10306   }
10307 
10308   /* get isrow, iscol and a local sequential matrix matseq[0] */
10309   if (reuse == MAT_INITIAL_MATRIX) {
10310     mloc_sub = PETSC_DECIDE;
10311     nloc_sub = PETSC_DECIDE;
10312     if (bs < 1) {
10313       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10314       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10315     } else {
10316       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10317       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10318     }
10319     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10320     rstart = rend - mloc_sub;
10321     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10322     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10323   } else { /* reuse == MAT_REUSE_MATRIX */
10324     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");
10325     /* retrieve subcomm */
10326     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10327     redund = (*matredundant)->redundant;
10328     isrow  = redund->isrow;
10329     iscol  = redund->iscol;
10330     matseq = redund->matseq;
10331   }
10332   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10333 
10334   /* get matredundant over subcomm */
10335   if (reuse == MAT_INITIAL_MATRIX) {
10336     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10337 
10338     /* create a supporting struct and attach it to C for reuse */
10339     PetscCall(PetscNew(&redund));
10340     (*matredundant)->redundant = redund;
10341     redund->isrow              = isrow;
10342     redund->iscol              = iscol;
10343     redund->matseq             = matseq;
10344     if (newsubcomm) {
10345       redund->subcomm = subcomm;
10346     } else {
10347       redund->subcomm = MPI_COMM_NULL;
10348     }
10349   } else {
10350     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10351   }
10352 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10353   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10354     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10355     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10356   }
10357 #endif
10358   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10359   PetscFunctionReturn(PETSC_SUCCESS);
10360 }
10361 
10362 /*@C
10363   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10364   a given `Mat`. Each submatrix can span multiple procs.
10365 
10366   Collective
10367 
10368   Input Parameters:
10369 + mat     - the matrix
10370 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10371 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10372 
10373   Output Parameter:
10374 . subMat - parallel sub-matrices each spanning a given `subcomm`
10375 
10376   Level: advanced
10377 
10378   Notes:
10379   The submatrix partition across processors is dictated by `subComm` a
10380   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10381   is not restricted to be grouped with consecutive original ranks.
10382 
10383   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10384   map directly to the layout of the original matrix [wrt the local
10385   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10386   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10387   the `subMat`. However the offDiagMat looses some columns - and this is
10388   reconstructed with `MatSetValues()`
10389 
10390   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10391 
10392 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10393 @*/
10394 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10395 {
10396   PetscMPIInt commsize, subCommSize;
10397 
10398   PetscFunctionBegin;
10399   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10400   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10401   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10402 
10403   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");
10404   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10405   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10406   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10407   PetscFunctionReturn(PETSC_SUCCESS);
10408 }
10409 
10410 /*@
10411   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10412 
10413   Not Collective
10414 
10415   Input Parameters:
10416 + mat   - matrix to extract local submatrix from
10417 . isrow - local row indices for submatrix
10418 - iscol - local column indices for submatrix
10419 
10420   Output Parameter:
10421 . submat - the submatrix
10422 
10423   Level: intermediate
10424 
10425   Notes:
10426   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10427 
10428   Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10429   the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10430 
10431   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10432   `MatSetValuesBlockedLocal()` will also be implemented.
10433 
10434   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10435   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10436 
10437 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10438 @*/
10439 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10440 {
10441   PetscFunctionBegin;
10442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10443   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10444   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10445   PetscCheckSameComm(isrow, 2, iscol, 3);
10446   PetscAssertPointer(submat, 4);
10447   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10448 
10449   if (mat->ops->getlocalsubmatrix) {
10450     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10451   } else {
10452     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10453   }
10454   PetscFunctionReturn(PETSC_SUCCESS);
10455 }
10456 
10457 /*@
10458   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10459 
10460   Not Collective
10461 
10462   Input Parameters:
10463 + mat    - matrix to extract local submatrix from
10464 . isrow  - local row indices for submatrix
10465 . iscol  - local column indices for submatrix
10466 - submat - the submatrix
10467 
10468   Level: intermediate
10469 
10470 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10471 @*/
10472 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10473 {
10474   PetscFunctionBegin;
10475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10476   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10477   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10478   PetscCheckSameComm(isrow, 2, iscol, 3);
10479   PetscAssertPointer(submat, 4);
10480   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10481 
10482   if (mat->ops->restorelocalsubmatrix) {
10483     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10484   } else {
10485     PetscCall(MatDestroy(submat));
10486   }
10487   *submat = NULL;
10488   PetscFunctionReturn(PETSC_SUCCESS);
10489 }
10490 
10491 /*@
10492   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10493 
10494   Collective
10495 
10496   Input Parameter:
10497 . mat - the matrix
10498 
10499   Output Parameter:
10500 . is - if any rows have zero diagonals this contains the list of them
10501 
10502   Level: developer
10503 
10504 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10505 @*/
10506 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10507 {
10508   PetscFunctionBegin;
10509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10510   PetscValidType(mat, 1);
10511   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10512   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10513 
10514   if (!mat->ops->findzerodiagonals) {
10515     Vec                diag;
10516     const PetscScalar *a;
10517     PetscInt          *rows;
10518     PetscInt           rStart, rEnd, r, nrow = 0;
10519 
10520     PetscCall(MatCreateVecs(mat, &diag, NULL));
10521     PetscCall(MatGetDiagonal(mat, diag));
10522     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10523     PetscCall(VecGetArrayRead(diag, &a));
10524     for (r = 0; r < rEnd - rStart; ++r)
10525       if (a[r] == 0.0) ++nrow;
10526     PetscCall(PetscMalloc1(nrow, &rows));
10527     nrow = 0;
10528     for (r = 0; r < rEnd - rStart; ++r)
10529       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10530     PetscCall(VecRestoreArrayRead(diag, &a));
10531     PetscCall(VecDestroy(&diag));
10532     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10533   } else {
10534     PetscUseTypeMethod(mat, findzerodiagonals, is);
10535   }
10536   PetscFunctionReturn(PETSC_SUCCESS);
10537 }
10538 
10539 /*@
10540   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10541 
10542   Collective
10543 
10544   Input Parameter:
10545 . mat - the matrix
10546 
10547   Output Parameter:
10548 . is - contains the list of rows with off block diagonal entries
10549 
10550   Level: developer
10551 
10552 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10553 @*/
10554 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10555 {
10556   PetscFunctionBegin;
10557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10558   PetscValidType(mat, 1);
10559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10561 
10562   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10563   PetscFunctionReturn(PETSC_SUCCESS);
10564 }
10565 
10566 /*@C
10567   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10568 
10569   Collective; No Fortran Support
10570 
10571   Input Parameter:
10572 . mat - the matrix
10573 
10574   Output Parameter:
10575 . values - the block inverses in column major order (FORTRAN-like)
10576 
10577   Level: advanced
10578 
10579   Notes:
10580   The size of the blocks is determined by the block size of the matrix.
10581 
10582   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10583 
10584   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10585 
10586 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10587 @*/
10588 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10589 {
10590   PetscFunctionBegin;
10591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10592   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10593   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10594   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10595   PetscFunctionReturn(PETSC_SUCCESS);
10596 }
10597 
10598 /*@C
10599   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10600 
10601   Collective; No Fortran Support
10602 
10603   Input Parameters:
10604 + mat     - the matrix
10605 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10606 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10607 
10608   Output Parameter:
10609 . values - the block inverses in column major order (FORTRAN-like)
10610 
10611   Level: advanced
10612 
10613   Notes:
10614   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10615 
10616   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10617 
10618 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10619 @*/
10620 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10621 {
10622   PetscFunctionBegin;
10623   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10624   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10625   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10626   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10627   PetscFunctionReturn(PETSC_SUCCESS);
10628 }
10629 
10630 /*@
10631   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10632 
10633   Collective
10634 
10635   Input Parameters:
10636 + A - the matrix
10637 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10638 
10639   Level: advanced
10640 
10641   Note:
10642   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10643 
10644 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10645 @*/
10646 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10647 {
10648   const PetscScalar *vals;
10649   PetscInt          *dnnz;
10650   PetscInt           m, rstart, rend, bs, i, j;
10651 
10652   PetscFunctionBegin;
10653   PetscCall(MatInvertBlockDiagonal(A, &vals));
10654   PetscCall(MatGetBlockSize(A, &bs));
10655   PetscCall(MatGetLocalSize(A, &m, NULL));
10656   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10657   PetscCall(PetscMalloc1(m / bs, &dnnz));
10658   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10659   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10660   PetscCall(PetscFree(dnnz));
10661   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10662   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10663   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10664   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10665   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10666   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10667   PetscFunctionReturn(PETSC_SUCCESS);
10668 }
10669 
10670 /*@C
10671   MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10672   via `MatTransposeColoringCreate()`.
10673 
10674   Collective
10675 
10676   Input Parameter:
10677 . c - coloring context
10678 
10679   Level: intermediate
10680 
10681 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10682 @*/
10683 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10684 {
10685   MatTransposeColoring matcolor = *c;
10686 
10687   PetscFunctionBegin;
10688   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10689   if (--((PetscObject)matcolor)->refct > 0) {
10690     matcolor = NULL;
10691     PetscFunctionReturn(PETSC_SUCCESS);
10692   }
10693 
10694   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10695   PetscCall(PetscFree(matcolor->rows));
10696   PetscCall(PetscFree(matcolor->den2sp));
10697   PetscCall(PetscFree(matcolor->colorforcol));
10698   PetscCall(PetscFree(matcolor->columns));
10699   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10700   PetscCall(PetscHeaderDestroy(c));
10701   PetscFunctionReturn(PETSC_SUCCESS);
10702 }
10703 
10704 /*@C
10705   MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10706   a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10707   `MatTransposeColoring` to sparse B.
10708 
10709   Collective
10710 
10711   Input Parameters:
10712 + coloring - coloring context created with `MatTransposeColoringCreate()`
10713 - B        - sparse matrix
10714 
10715   Output Parameter:
10716 . Btdense - dense matrix B^T
10717 
10718   Level: developer
10719 
10720   Note:
10721   These are used internally for some implementations of `MatRARt()`
10722 
10723 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10724 @*/
10725 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10726 {
10727   PetscFunctionBegin;
10728   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10729   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10730   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10731 
10732   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10733   PetscFunctionReturn(PETSC_SUCCESS);
10734 }
10735 
10736 /*@C
10737   MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10738   a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10739   in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10740   `Csp` from `Cden`.
10741 
10742   Collective
10743 
10744   Input Parameters:
10745 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10746 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10747 
10748   Output Parameter:
10749 . Csp - sparse matrix
10750 
10751   Level: developer
10752 
10753   Note:
10754   These are used internally for some implementations of `MatRARt()`
10755 
10756 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10757 @*/
10758 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10759 {
10760   PetscFunctionBegin;
10761   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10762   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10763   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10764 
10765   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10766   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10767   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10768   PetscFunctionReturn(PETSC_SUCCESS);
10769 }
10770 
10771 /*@C
10772   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10773 
10774   Collective
10775 
10776   Input Parameters:
10777 + mat        - the matrix product C
10778 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10779 
10780   Output Parameter:
10781 . color - the new coloring context
10782 
10783   Level: intermediate
10784 
10785 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10786           `MatTransColoringApplyDenToSp()`
10787 @*/
10788 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10789 {
10790   MatTransposeColoring c;
10791   MPI_Comm             comm;
10792 
10793   PetscFunctionBegin;
10794   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10795   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10796   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10797 
10798   c->ctype = iscoloring->ctype;
10799   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10800 
10801   *color = c;
10802   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10803   PetscFunctionReturn(PETSC_SUCCESS);
10804 }
10805 
10806 /*@
10807   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10808   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10809   same, otherwise it will be larger
10810 
10811   Not Collective
10812 
10813   Input Parameter:
10814 . mat - the matrix
10815 
10816   Output Parameter:
10817 . state - the current state
10818 
10819   Level: intermediate
10820 
10821   Notes:
10822   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10823   different matrices
10824 
10825   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10826 
10827   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10828 
10829 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10830 @*/
10831 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10832 {
10833   PetscFunctionBegin;
10834   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10835   *state = mat->nonzerostate;
10836   PetscFunctionReturn(PETSC_SUCCESS);
10837 }
10838 
10839 /*@
10840   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10841   matrices from each processor
10842 
10843   Collective
10844 
10845   Input Parameters:
10846 + comm   - the communicators the parallel matrix will live on
10847 . seqmat - the input sequential matrices
10848 . n      - number of local columns (or `PETSC_DECIDE`)
10849 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10850 
10851   Output Parameter:
10852 . mpimat - the parallel matrix generated
10853 
10854   Level: developer
10855 
10856   Note:
10857   The number of columns of the matrix in EACH processor MUST be the same.
10858 
10859 .seealso: [](ch_matrices), `Mat`
10860 @*/
10861 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10862 {
10863   PetscMPIInt size;
10864 
10865   PetscFunctionBegin;
10866   PetscCallMPI(MPI_Comm_size(comm, &size));
10867   if (size == 1) {
10868     if (reuse == MAT_INITIAL_MATRIX) {
10869       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10870     } else {
10871       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10872     }
10873     PetscFunctionReturn(PETSC_SUCCESS);
10874   }
10875 
10876   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");
10877 
10878   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10879   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10880   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10881   PetscFunctionReturn(PETSC_SUCCESS);
10882 }
10883 
10884 /*@
10885   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10886 
10887   Collective
10888 
10889   Input Parameters:
10890 + A - the matrix to create subdomains from
10891 - N - requested number of subdomains
10892 
10893   Output Parameters:
10894 + n   - number of subdomains resulting on this MPI process
10895 - iss - `IS` list with indices of subdomains on this MPI process
10896 
10897   Level: advanced
10898 
10899   Note:
10900   The number of subdomains must be smaller than the communicator size
10901 
10902 .seealso: [](ch_matrices), `Mat`, `IS`
10903 @*/
10904 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10905 {
10906   MPI_Comm    comm, subcomm;
10907   PetscMPIInt size, rank, color;
10908   PetscInt    rstart, rend, k;
10909 
10910   PetscFunctionBegin;
10911   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10912   PetscCallMPI(MPI_Comm_size(comm, &size));
10913   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10914   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);
10915   *n    = 1;
10916   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10917   color = rank / k;
10918   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10919   PetscCall(PetscMalloc1(1, iss));
10920   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10921   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10922   PetscCallMPI(MPI_Comm_free(&subcomm));
10923   PetscFunctionReturn(PETSC_SUCCESS);
10924 }
10925 
10926 /*@
10927   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10928 
10929   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10930   If they are not the same, uses `MatMatMatMult()`.
10931 
10932   Once the coarse grid problem is constructed, correct for interpolation operators
10933   that are not of full rank, which can legitimately happen in the case of non-nested
10934   geometric multigrid.
10935 
10936   Input Parameters:
10937 + restrct     - restriction operator
10938 . dA          - fine grid matrix
10939 . interpolate - interpolation operator
10940 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10941 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10942 
10943   Output Parameter:
10944 . A - the Galerkin coarse matrix
10945 
10946   Options Database Key:
10947 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10948 
10949   Level: developer
10950 
10951 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10952 @*/
10953 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10954 {
10955   IS  zerorows;
10956   Vec diag;
10957 
10958   PetscFunctionBegin;
10959   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10960   /* Construct the coarse grid matrix */
10961   if (interpolate == restrct) {
10962     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10963   } else {
10964     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10965   }
10966 
10967   /* If the interpolation matrix is not of full rank, A will have zero rows.
10968      This can legitimately happen in the case of non-nested geometric multigrid.
10969      In that event, we set the rows of the matrix to the rows of the identity,
10970      ignoring the equations (as the RHS will also be zero). */
10971 
10972   PetscCall(MatFindZeroRows(*A, &zerorows));
10973 
10974   if (zerorows != NULL) { /* if there are any zero rows */
10975     PetscCall(MatCreateVecs(*A, &diag, NULL));
10976     PetscCall(MatGetDiagonal(*A, diag));
10977     PetscCall(VecISSet(diag, zerorows, 1.0));
10978     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10979     PetscCall(VecDestroy(&diag));
10980     PetscCall(ISDestroy(&zerorows));
10981   }
10982   PetscFunctionReturn(PETSC_SUCCESS);
10983 }
10984 
10985 /*@C
10986   MatSetOperation - Allows user to set a matrix operation for any matrix type
10987 
10988   Logically Collective
10989 
10990   Input Parameters:
10991 + mat - the matrix
10992 . op  - the name of the operation
10993 - f   - the function that provides the operation
10994 
10995   Level: developer
10996 
10997   Example Usage:
10998 .vb
10999   extern PetscErrorCode usermult(Mat, Vec, Vec);
11000 
11001   PetscCall(MatCreateXXX(comm, ..., &A));
11002   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11003 .ve
11004 
11005   Notes:
11006   See the file `include/petscmat.h` for a complete list of matrix
11007   operations, which all have the form MATOP_<OPERATION>, where
11008   <OPERATION> is the name (in all capital letters) of the
11009   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11010 
11011   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11012   sequence as the usual matrix interface routines, since they
11013   are intended to be accessed via the usual matrix interface
11014   routines, e.g.,
11015 .vb
11016   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11017 .ve
11018 
11019   In particular each function MUST return `PETSC_SUCCESS` on success and
11020   nonzero on failure.
11021 
11022   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11023 
11024 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11025 @*/
11026 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11027 {
11028   PetscFunctionBegin;
11029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11030   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11031   (((void (**)(void))mat->ops)[op]) = f;
11032   PetscFunctionReturn(PETSC_SUCCESS);
11033 }
11034 
11035 /*@C
11036   MatGetOperation - Gets a matrix operation for any matrix type.
11037 
11038   Not Collective
11039 
11040   Input Parameters:
11041 + mat - the matrix
11042 - op  - the name of the operation
11043 
11044   Output Parameter:
11045 . f - the function that provides the operation
11046 
11047   Level: developer
11048 
11049   Example Usage:
11050 .vb
11051   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11052 
11053   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11054 .ve
11055 
11056   Notes:
11057   See the file include/petscmat.h for a complete list of matrix
11058   operations, which all have the form MATOP_<OPERATION>, where
11059   <OPERATION> is the name (in all capital letters) of the
11060   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11061 
11062   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11063 
11064 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11065 @*/
11066 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11067 {
11068   PetscFunctionBegin;
11069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11070   *f = (((void (**)(void))mat->ops)[op]);
11071   PetscFunctionReturn(PETSC_SUCCESS);
11072 }
11073 
11074 /*@
11075   MatHasOperation - Determines whether the given matrix supports the particular operation.
11076 
11077   Not Collective
11078 
11079   Input Parameters:
11080 + mat - the matrix
11081 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11082 
11083   Output Parameter:
11084 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11085 
11086   Level: advanced
11087 
11088   Note:
11089   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11090 
11091 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11092 @*/
11093 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11094 {
11095   PetscFunctionBegin;
11096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11097   PetscAssertPointer(has, 3);
11098   if (mat->ops->hasoperation) {
11099     PetscUseTypeMethod(mat, hasoperation, op, has);
11100   } else {
11101     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11102     else {
11103       *has = PETSC_FALSE;
11104       if (op == MATOP_CREATE_SUBMATRIX) {
11105         PetscMPIInt size;
11106 
11107         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11108         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11109       }
11110     }
11111   }
11112   PetscFunctionReturn(PETSC_SUCCESS);
11113 }
11114 
11115 /*@
11116   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11117 
11118   Collective
11119 
11120   Input Parameter:
11121 . mat - the matrix
11122 
11123   Output Parameter:
11124 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11125 
11126   Level: beginner
11127 
11128 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11129 @*/
11130 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11131 {
11132   PetscFunctionBegin;
11133   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11134   PetscValidType(mat, 1);
11135   PetscAssertPointer(cong, 2);
11136   if (!mat->rmap || !mat->cmap) {
11137     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11138     PetscFunctionReturn(PETSC_SUCCESS);
11139   }
11140   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11141     PetscCall(PetscLayoutSetUp(mat->rmap));
11142     PetscCall(PetscLayoutSetUp(mat->cmap));
11143     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11144     if (*cong) mat->congruentlayouts = 1;
11145     else mat->congruentlayouts = 0;
11146   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11147   PetscFunctionReturn(PETSC_SUCCESS);
11148 }
11149 
11150 PetscErrorCode MatSetInf(Mat A)
11151 {
11152   PetscFunctionBegin;
11153   PetscUseTypeMethod(A, setinf);
11154   PetscFunctionReturn(PETSC_SUCCESS);
11155 }
11156 
11157 /*@C
11158   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
11159   and possibly removes small values from the graph structure.
11160 
11161   Collective
11162 
11163   Input Parameters:
11164 + A      - the matrix
11165 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11166 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11167 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11168 
11169   Output Parameter:
11170 . graph - the resulting graph
11171 
11172   Level: advanced
11173 
11174 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11175 @*/
11176 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11177 {
11178   PetscFunctionBegin;
11179   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11180   PetscValidType(A, 1);
11181   PetscValidLogicalCollectiveBool(A, scale, 3);
11182   PetscAssertPointer(graph, 5);
11183   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11184   PetscFunctionReturn(PETSC_SUCCESS);
11185 }
11186 
11187 /*@
11188   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11189   meaning the same memory is used for the matrix, and no new memory is allocated.
11190 
11191   Collective
11192 
11193   Input Parameters:
11194 + A    - the matrix
11195 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well
11196 
11197   Level: intermediate
11198 
11199   Developer Notes:
11200   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11201   of the arrays in the data structure are unneeded.
11202 
11203 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11204 @*/
11205 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11206 {
11207   PetscFunctionBegin;
11208   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11209   PetscUseTypeMethod(A, eliminatezeros, keep);
11210   PetscFunctionReturn(PETSC_SUCCESS);
11211 }
11212