xref: /petsc/src/mat/interface/matrix.c (revision dd01b7e5d0240168a3219b4548f06eb476d9d69f)
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()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 . mat - the matrix
257 
258   Output Parameter:
259 . keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264   `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscAssertPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282   MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 . mat - the matrix
286 
287   Output Parameter:
288 . zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293   `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscAssertPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323   Not Collective
324 
325   Input Parameter:
326 . A - the matrix
327 
328   Output Parameter:
329 . a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331   Level: advanced
332 
333   Notes:
334   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscAssertPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361   Collective
362 
363   Input Parameter:
364 . mat - the matrix
365 
366   Output Parameter:
367 . trace - the sum of the diagonal entries
368 
369   Level: advanced
370 
371 .seealso: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388   MatRealPart - Zeros out the imaginary part of the matrix
389 
390   Logically Collective
391 
392   Input Parameter:
393 . mat - the matrix
394 
395   Level: advanced
396 
397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414   Collective
415 
416   Input Parameter:
417 . mat - the matrix
418 
419   Output Parameters:
420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 - ghosts  - the global indices of the ghost points
422 
423   Level: advanced
424 
425   Note:
426   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448   Logically Collective
449 
450   Input Parameter:
451 . mat - the matrix
452 
453   Level: advanced
454 
455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472   Not Collective
473 
474   Input Parameter:
475 . mat - the matrix
476 
477   Output Parameters:
478 + missing - is any diagonal missing
479 - dd      - first diagonal entry that is missing (optional) on this process
480 
481   Level: advanced
482 
483 .seealso: [](ch_matrices), `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscAssertPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
498 /*@C
499   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
500   for each row that you get to ensure that your application does
501   not bleed memory.
502 
503   Not Collective
504 
505   Input Parameters:
506 + mat - the matrix
507 - row - the row to get
508 
509   Output Parameters:
510 + ncols - if not `NULL`, the number of nonzeros in the row
511 . cols  - if not `NULL`, the column numbers
512 - vals  - if not `NULL`, the values
513 
514   Level: advanced
515 
516   Notes:
517   This routine is provided for people who need to have direct access
518   to the structure of a matrix.  We hope that we provide enough
519   high-level matrix routines that few users will need it.
520 
521   `MatGetRow()` always returns 0-based column indices, regardless of
522   whether the internal representation is 0-based (default) or 1-based.
523 
524   For better efficiency, set cols and/or vals to `NULL` if you do
525   not wish to extract these quantities.
526 
527   The user can only examine the values extracted with `MatGetRow()`;
528   the values cannot be altered.  To change the matrix entries, one
529   must use `MatSetValues()`.
530 
531   You can only have one call to `MatGetRow()` outstanding for a particular
532   matrix at a time, per processor. `MatGetRow()` can only obtain rows
533   associated with the given processor, it cannot get rows from the
534   other processors; for that we suggest using `MatCreateSubMatrices()`, then
535   MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
536   is in the global number of rows.
537 
538   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
539 
540   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
541 
542   Fortran Notes:
543   The calling sequence is
544 .vb
545    MatGetRow(matrix,row,ncols,cols,values,ierr)
546          Mat     matrix (input)
547          integer row    (input)
548          integer ncols  (output)
549          integer cols(maxcols) (output)
550          double precision (or double complex) values(maxcols) output
551 .ve
552   where maxcols >= maximum nonzeros in any row of the matrix.
553 
554   Caution:
555   Do not try to change the contents of the output arrays (`cols` and `vals`).
556   In some cases, this may corrupt the matrix.
557 
558 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
559 @*/
560 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
561 {
562   PetscInt incols;
563 
564   PetscFunctionBegin;
565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
566   PetscValidType(mat, 1);
567   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
568   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
569   MatCheckPreallocated(mat, 1);
570   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);
571   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
572   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
573   if (ncols) *ncols = incols;
574   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
575   PetscFunctionReturn(PETSC_SUCCESS);
576 }
577 
578 /*@
579   MatConjugate - replaces the matrix values with their complex conjugates
580 
581   Logically Collective
582 
583   Input Parameter:
584 . mat - the matrix
585 
586   Level: advanced
587 
588 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
589 @*/
590 PetscErrorCode MatConjugate(Mat mat)
591 {
592   PetscFunctionBegin;
593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
595   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
596     PetscUseTypeMethod(mat, conjugate);
597     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
598   }
599   PetscFunctionReturn(PETSC_SUCCESS);
600 }
601 
602 /*@C
603   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
604 
605   Not Collective
606 
607   Input Parameters:
608 + mat   - the matrix
609 . row   - the row to get
610 . ncols - the number of nonzeros
611 . cols  - the columns of the nonzeros
612 - vals  - if nonzero the column values
613 
614   Level: advanced
615 
616   Notes:
617   This routine should be called after you have finished examining the entries.
618 
619   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
620   us of the array after it has been restored. If you pass `NULL`, it will
621   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
622 
623   Fortran Notes:
624   The calling sequence is
625 .vb
626    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
627       Mat     matrix (input)
628       integer row    (input)
629       integer ncols  (output)
630       integer cols(maxcols) (output)
631       double precision (or double complex) values(maxcols) output
632 .ve
633   Where maxcols >= maximum nonzeros in any row of the matrix.
634 
635   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
636   before another call to `MatGetRow()` can be made.
637 
638 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
639 @*/
640 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
641 {
642   PetscFunctionBegin;
643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
644   if (ncols) PetscAssertPointer(ncols, 3);
645   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
646   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
647   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
648   if (ncols) *ncols = 0;
649   if (cols) *cols = NULL;
650   if (vals) *vals = NULL;
651   PetscFunctionReturn(PETSC_SUCCESS);
652 }
653 
654 /*@
655   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
656   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
657 
658   Not Collective
659 
660   Input Parameter:
661 . mat - the matrix
662 
663   Level: advanced
664 
665   Note:
666   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.
667 
668 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
669 @*/
670 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
671 {
672   PetscFunctionBegin;
673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
674   PetscValidType(mat, 1);
675   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
676   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
677   MatCheckPreallocated(mat, 1);
678   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
679   PetscUseTypeMethod(mat, getrowuppertriangular);
680   PetscFunctionReturn(PETSC_SUCCESS);
681 }
682 
683 /*@
684   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
685 
686   Not Collective
687 
688   Input Parameter:
689 . mat - the matrix
690 
691   Level: advanced
692 
693   Note:
694   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
695 
696 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
697 @*/
698 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
699 {
700   PetscFunctionBegin;
701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
702   PetscValidType(mat, 1);
703   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
704   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
705   MatCheckPreallocated(mat, 1);
706   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
707   PetscUseTypeMethod(mat, restorerowuppertriangular);
708   PetscFunctionReturn(PETSC_SUCCESS);
709 }
710 
711 /*@C
712   MatSetOptionsPrefix - Sets the prefix used for searching for all
713   `Mat` options in the database.
714 
715   Logically Collective
716 
717   Input Parameters:
718 + A      - the matrix
719 - prefix - the prefix to prepend to all option names
720 
721   Level: advanced
722 
723   Notes:
724   A hyphen (-) must NOT be given at the beginning of the prefix name.
725   The first character of all runtime options is AUTOMATICALLY the hyphen.
726 
727   This is NOT used for options for the factorization of the matrix. Normally the
728   prefix is automatically passed in from the PC calling the factorization. To set
729   it directly use  `MatSetOptionsPrefixFactor()`
730 
731 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
732 @*/
733 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
734 {
735   PetscFunctionBegin;
736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
737   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
738   PetscFunctionReturn(PETSC_SUCCESS);
739 }
740 
741 /*@C
742   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
743   for matrices created with `MatGetFactor()`
744 
745   Logically Collective
746 
747   Input Parameters:
748 + A      - the matrix
749 - prefix - the prefix to prepend to all option names for the factored matrix
750 
751   Level: developer
752 
753   Notes:
754   A hyphen (-) must NOT be given at the beginning of the prefix name.
755   The first character of all runtime options is AUTOMATICALLY the hyphen.
756 
757   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
758   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
759 
760 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
761 @*/
762 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
763 {
764   PetscFunctionBegin;
765   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
766   if (prefix) {
767     PetscAssertPointer(prefix, 2);
768     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
769     if (prefix != A->factorprefix) {
770       PetscCall(PetscFree(A->factorprefix));
771       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
772     }
773   } else PetscCall(PetscFree(A->factorprefix));
774   PetscFunctionReturn(PETSC_SUCCESS);
775 }
776 
777 /*@C
778   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
779   for matrices created with `MatGetFactor()`
780 
781   Logically Collective
782 
783   Input Parameters:
784 + A      - the matrix
785 - prefix - the prefix to prepend to all option names for the factored matrix
786 
787   Level: developer
788 
789   Notes:
790   A hyphen (-) must NOT be given at the beginning of the prefix name.
791   The first character of all runtime options is AUTOMATICALLY the hyphen.
792 
793   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
794   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
795 
796 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
797           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
798           `MatSetOptionsPrefix()`
799 @*/
800 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
801 {
802   size_t len1, len2, new_len;
803 
804   PetscFunctionBegin;
805   PetscValidHeader(A, 1);
806   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
807   if (!A->factorprefix) {
808     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
809     PetscFunctionReturn(PETSC_SUCCESS);
810   }
811   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
812 
813   PetscCall(PetscStrlen(A->factorprefix, &len1));
814   PetscCall(PetscStrlen(prefix, &len2));
815   new_len = len1 + len2 + 1;
816   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
817   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
818   PetscFunctionReturn(PETSC_SUCCESS);
819 }
820 
821 /*@C
822   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
823   matrix options in the database.
824 
825   Logically Collective
826 
827   Input Parameters:
828 + A      - the matrix
829 - prefix - the prefix to prepend to all option names
830 
831   Level: advanced
832 
833   Note:
834   A hyphen (-) must NOT be given at the beginning of the prefix name.
835   The first character of all runtime options is AUTOMATICALLY the hyphen.
836 
837 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
838 @*/
839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
840 {
841   PetscFunctionBegin;
842   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
843   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
844   PetscFunctionReturn(PETSC_SUCCESS);
845 }
846 
847 /*@C
848   MatGetOptionsPrefix - Gets the prefix used for searching for all
849   matrix options in the database.
850 
851   Not Collective
852 
853   Input Parameter:
854 . A - the matrix
855 
856   Output Parameter:
857 . prefix - pointer to the prefix string used
858 
859   Level: advanced
860 
861   Fortran Notes:
862   The user should pass in a string `prefix` of
863   sufficient length to hold the prefix.
864 
865 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
866 @*/
867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
868 {
869   PetscFunctionBegin;
870   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
871   PetscAssertPointer(prefix, 2);
872   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
873   PetscFunctionReturn(PETSC_SUCCESS);
874 }
875 
876 /*@
877   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
878 
879   Collective
880 
881   Input Parameter:
882 . A - the matrix
883 
884   Level: beginner
885 
886   Notes:
887   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
888 
889   Users can reset the preallocation to access the original memory.
890 
891   Currently only supported for  `MATAIJ` matrices.
892 
893 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
894 @*/
895 PetscErrorCode MatResetPreallocation(Mat A)
896 {
897   PetscFunctionBegin;
898   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
899   PetscValidType(A, 1);
900   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()");
901   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
902   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
903   PetscFunctionReturn(PETSC_SUCCESS);
904 }
905 
906 /*@
907   MatSetUp - Sets up the internal matrix data structures for later use.
908 
909   Collective
910 
911   Input Parameter:
912 . A - the matrix
913 
914   Level: intermediate
915 
916   Notes:
917   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
918   setting values in the matrix.
919 
920   If a suitable preallocation routine is used, this function does not need to be called.
921 
922   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
923 
924 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
925 @*/
926 PetscErrorCode MatSetUp(Mat A)
927 {
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
930   if (!((PetscObject)A)->type_name) {
931     PetscMPIInt size;
932 
933     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
934     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
935   }
936   if (!A->preallocated) PetscTryTypeMethod(A, setup);
937   PetscCall(PetscLayoutSetUp(A->rmap));
938   PetscCall(PetscLayoutSetUp(A->cmap));
939   A->preallocated = PETSC_TRUE;
940   PetscFunctionReturn(PETSC_SUCCESS);
941 }
942 
943 #if defined(PETSC_HAVE_SAWS)
944   #include <petscviewersaws.h>
945 #endif
946 
947 /*
948    If threadsafety is on extraneous matrices may be printed
949 
950    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
951 */
952 #if !defined(PETSC_HAVE_THREADSAFETY)
953 static PetscInt insidematview = 0;
954 #endif
955 
956 /*@C
957   MatViewFromOptions - View properties of the matrix based on options set in the options database
958 
959   Collective
960 
961   Input Parameters:
962 + A    - the matrix
963 . obj  - optional additional object that provides the options prefix to use
964 - name - command line option
965 
966   Options Database Key:
967 . -mat_view [viewertype]:... - the viewer and its options
968 
969   Level: intermediate
970 
971   Notes:
972 .vb
973     If no value is provided ascii:stdout is used
974        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
975                                                   for example ascii::ascii_info prints just the information about the object not all details
976                                                   unless :append is given filename opens in write mode, overwriting what was already there
977        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
978        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
979        socket[:port]                             defaults to the standard output port
980        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
981 .ve
982 
983 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
984 @*/
985 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
986 {
987   PetscFunctionBegin;
988   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
989 #if !defined(PETSC_HAVE_THREADSAFETY)
990   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
991 #endif
992   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
993   PetscFunctionReturn(PETSC_SUCCESS);
994 }
995 
996 /*@C
997   MatView - display information about a matrix in a variety ways
998 
999   Collective
1000 
1001   Input Parameters:
1002 + mat    - the matrix
1003 - viewer - visualization context
1004 
1005   Options Database Keys:
1006 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1007 . -mat_view ::ascii_info_detail    - Prints more detailed info
1008 . -mat_view                        - Prints matrix in ASCII format
1009 . -mat_view ::ascii_matlab         - Prints matrix in Matlab format
1010 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1011 . -display <name>                  - Sets display name (default is host)
1012 . -draw_pause <sec>                - Sets number of seconds to pause after display
1013 . -mat_view socket                 - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1014 . -viewer_socket_machine <machine> - -
1015 . -viewer_socket_port <port>       - -
1016 . -mat_view binary                 - save matrix to file in binary format
1017 - -viewer_binary_filename <name>   - -
1018 
1019   Level: beginner
1020 
1021   Notes:
1022   The available visualization contexts include
1023 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1024 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1025 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1026 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1027 
1028   The user can open alternative visualization contexts with
1029 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1030 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1031   specified file; corresponding input uses `MatLoad()`
1032 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1033   an X window display
1034 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1035   Currently only the `MATSEQDENSE` and `MATAIJ`
1036   matrix types support the Socket viewer.
1037 
1038   The user can call `PetscViewerPushFormat()` to specify the output
1039   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1040   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1041 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1042 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1043 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1044 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1045   format common among all matrix types
1046 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1047   format (which is in many cases the same as the default)
1048 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1049   size and structure (not the matrix entries)
1050 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1051   the matrix structure
1052 
1053   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1054   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1055 
1056   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1057 
1058   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1059   viewer is used.
1060 
1061   See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1062   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1063 
1064   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1065   and then use the following mouse functions.
1066 .vb
1067   left mouse: zoom in
1068   middle mouse: zoom out
1069   right mouse: continue with the simulation
1070 .ve
1071 
1072 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1073           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1074 @*/
1075 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1076 {
1077   PetscInt          rows, cols, rbs, cbs;
1078   PetscBool         isascii, isstring, issaws;
1079   PetscViewerFormat format;
1080   PetscMPIInt       size;
1081 
1082   PetscFunctionBegin;
1083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1084   PetscValidType(mat, 1);
1085   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1086   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1087   PetscCheckSameComm(mat, 1, viewer, 2);
1088 
1089   PetscCall(PetscViewerGetFormat(viewer, &format));
1090   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1091   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1092 
1093 #if !defined(PETSC_HAVE_THREADSAFETY)
1094   insidematview++;
1095 #endif
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1098   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1099   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");
1100 
1101   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1102   if (isascii) {
1103     if (!mat->preallocated) {
1104       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1105 #if !defined(PETSC_HAVE_THREADSAFETY)
1106       insidematview--;
1107 #endif
1108       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1109       PetscFunctionReturn(PETSC_SUCCESS);
1110     }
1111     if (!mat->assembled) {
1112       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1113 #if !defined(PETSC_HAVE_THREADSAFETY)
1114       insidematview--;
1115 #endif
1116       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1117       PetscFunctionReturn(PETSC_SUCCESS);
1118     }
1119     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1120     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1121       MatNullSpace nullsp, transnullsp;
1122 
1123       PetscCall(PetscViewerASCIIPushTab(viewer));
1124       PetscCall(MatGetSize(mat, &rows, &cols));
1125       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1126       if (rbs != 1 || cbs != 1) {
1127         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1128         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1129       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1130       if (mat->factortype) {
1131         MatSolverType solver;
1132         PetscCall(MatFactorGetSolverType(mat, &solver));
1133         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1134       }
1135       if (mat->ops->getinfo) {
1136         MatInfo info;
1137         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1138         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1139         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1140       }
1141       PetscCall(MatGetNullSpace(mat, &nullsp));
1142       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1144       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1145       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1146       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1147       PetscCall(PetscViewerASCIIPushTab(viewer));
1148       PetscCall(MatProductView(mat, viewer));
1149       PetscCall(PetscViewerASCIIPopTab(viewer));
1150     }
1151   } else if (issaws) {
1152 #if defined(PETSC_HAVE_SAWS)
1153     PetscMPIInt rank;
1154 
1155     PetscCall(PetscObjectName((PetscObject)mat));
1156     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1157     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1158 #endif
1159   } else if (isstring) {
1160     const char *type;
1161     PetscCall(MatGetType(mat, &type));
1162     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1163     PetscTryTypeMethod(mat, view, viewer);
1164   }
1165   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1166     PetscCall(PetscViewerASCIIPushTab(viewer));
1167     PetscUseTypeMethod(mat, viewnative, viewer);
1168     PetscCall(PetscViewerASCIIPopTab(viewer));
1169   } else if (mat->ops->view) {
1170     PetscCall(PetscViewerASCIIPushTab(viewer));
1171     PetscUseTypeMethod(mat, view, viewer);
1172     PetscCall(PetscViewerASCIIPopTab(viewer));
1173   }
1174   if (isascii) {
1175     PetscCall(PetscViewerGetFormat(viewer, &format));
1176     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1177   }
1178   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1179 #if !defined(PETSC_HAVE_THREADSAFETY)
1180   insidematview--;
1181 #endif
1182   PetscFunctionReturn(PETSC_SUCCESS);
1183 }
1184 
1185 #if defined(PETSC_USE_DEBUG)
1186   #include <../src/sys/totalview/tv_data_display.h>
1187 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1188 {
1189   TV_add_row("Local rows", "int", &mat->rmap->n);
1190   TV_add_row("Local columns", "int", &mat->cmap->n);
1191   TV_add_row("Global rows", "int", &mat->rmap->N);
1192   TV_add_row("Global columns", "int", &mat->cmap->N);
1193   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1194   return TV_format_OK;
1195 }
1196 #endif
1197 
1198 /*@C
1199   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1200   with `MatView()`.  The matrix format is determined from the options database.
1201   Generates a parallel MPI matrix if the communicator has more than one
1202   processor.  The default matrix type is `MATAIJ`.
1203 
1204   Collective
1205 
1206   Input Parameters:
1207 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1208             or some related function before a call to `MatLoad()`
1209 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1210 
1211   Options Database Keys:
1212    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1213    block size
1214 . -matload_block_size <bs> - set block size
1215 
1216   Level: beginner
1217 
1218   Notes:
1219   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1220   `Mat` before calling this routine if you wish to set it from the options database.
1221 
1222   `MatLoad()` automatically loads into the options database any options
1223   given in the file filename.info where filename is the name of the file
1224   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1225   file will be ignored if you use the -viewer_binary_skip_info option.
1226 
1227   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1228   sets the default matrix type AIJ and sets the local and global sizes.
1229   If type and/or size is already set, then the same are used.
1230 
1231   In parallel, each processor can load a subset of rows (or the
1232   entire matrix).  This routine is especially useful when a large
1233   matrix is stored on disk and only part of it is desired on each
1234   processor.  For example, a parallel solver may access only some of
1235   the rows from each processor.  The algorithm used here reads
1236   relatively small blocks of data rather than reading the entire
1237   matrix and then subsetting it.
1238 
1239   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1240   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1241   or the sequence like
1242 .vb
1243     `PetscViewer` v;
1244     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1245     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1246     `PetscViewerSetFromOptions`(v);
1247     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1248     `PetscViewerFileSetName`(v,"datafile");
1249 .ve
1250   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1251 $ -viewer_type {binary, hdf5}
1252 
1253   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1254   and src/mat/tutorials/ex10.c with the second approach.
1255 
1256   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1257   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1258   Multiple objects, both matrices and vectors, can be stored within the same file.
1259   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1260 
1261   Most users should not need to know the details of the binary storage
1262   format, since `MatLoad()` and `MatView()` completely hide these details.
1263   But for anyone who is interested, the standard binary matrix storage
1264   format is
1265 
1266 .vb
1267     PetscInt    MAT_FILE_CLASSID
1268     PetscInt    number of rows
1269     PetscInt    number of columns
1270     PetscInt    total number of nonzeros
1271     PetscInt    *number nonzeros in each row
1272     PetscInt    *column indices of all nonzeros (starting index is zero)
1273     PetscScalar *values of all nonzeros
1274 .ve
1275   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1276   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
1277   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1278 
1279   PETSc automatically does the byte swapping for
1280   machines that store the bytes reversed. Thus if you write your own binary
1281   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1282   and `PetscBinaryWrite()` to see how this may be done.
1283 
1284   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1285   Each processor's chunk is loaded independently by its owning MPI process.
1286   Multiple objects, both matrices and vectors, can be stored within the same file.
1287   They are looked up by their PetscObject name.
1288 
1289   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1290   by default the same structure and naming of the AIJ arrays and column count
1291   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1292 $    save example.mat A b -v7.3
1293   can be directly read by this routine (see Reference 1 for details).
1294 
1295   Depending on your MATLAB version, this format might be a default,
1296   otherwise you can set it as default in Preferences.
1297 
1298   Unless -nocompression flag is used to save the file in MATLAB,
1299   PETSc must be configured with ZLIB package.
1300 
1301   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1302 
1303   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1304 
1305   Corresponding `MatView()` is not yet implemented.
1306 
1307   The loaded matrix is actually a transpose of the original one in MATLAB,
1308   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1309   With this format, matrix is automatically transposed by PETSc,
1310   unless the matrix is marked as SPD or symmetric
1311   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1312 
1313   References:
1314 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1315 
1316 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1317  @*/
1318 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1319 {
1320   PetscBool flg;
1321 
1322   PetscFunctionBegin;
1323   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1324   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1325 
1326   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1327 
1328   flg = PETSC_FALSE;
1329   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1330   if (flg) {
1331     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1332     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1333   }
1334   flg = PETSC_FALSE;
1335   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1336   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1337 
1338   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1339   PetscUseTypeMethod(mat, load, viewer);
1340   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1341   PetscFunctionReturn(PETSC_SUCCESS);
1342 }
1343 
1344 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1345 {
1346   Mat_Redundant *redund = *redundant;
1347 
1348   PetscFunctionBegin;
1349   if (redund) {
1350     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1351       PetscCall(ISDestroy(&redund->isrow));
1352       PetscCall(ISDestroy(&redund->iscol));
1353       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1354     } else {
1355       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1356       PetscCall(PetscFree(redund->sbuf_j));
1357       PetscCall(PetscFree(redund->sbuf_a));
1358       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1359         PetscCall(PetscFree(redund->rbuf_j[i]));
1360         PetscCall(PetscFree(redund->rbuf_a[i]));
1361       }
1362       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1363     }
1364 
1365     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1366     PetscCall(PetscFree(redund));
1367   }
1368   PetscFunctionReturn(PETSC_SUCCESS);
1369 }
1370 
1371 /*@C
1372   MatDestroy - Frees space taken by a matrix.
1373 
1374   Collective
1375 
1376   Input Parameter:
1377 . A - the matrix
1378 
1379   Level: beginner
1380 
1381   Developer Notes:
1382   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1383   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1384   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1385   if changes are needed here.
1386 
1387 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1388 @*/
1389 PetscErrorCode MatDestroy(Mat *A)
1390 {
1391   PetscFunctionBegin;
1392   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1393   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1394   if (--((PetscObject)(*A))->refct > 0) {
1395     *A = NULL;
1396     PetscFunctionReturn(PETSC_SUCCESS);
1397   }
1398 
1399   /* if memory was published with SAWs then destroy it */
1400   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1401   PetscTryTypeMethod((*A), destroy);
1402 
1403   PetscCall(PetscFree((*A)->factorprefix));
1404   PetscCall(PetscFree((*A)->defaultvectype));
1405   PetscCall(PetscFree((*A)->defaultrandtype));
1406   PetscCall(PetscFree((*A)->bsizes));
1407   PetscCall(PetscFree((*A)->solvertype));
1408   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1409   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1410   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1411   PetscCall(MatProductClear(*A));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1413   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1414   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1415   PetscCall(MatDestroy(&(*A)->schur));
1416   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1417   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1418   PetscCall(PetscHeaderDestroy(A));
1419   PetscFunctionReturn(PETSC_SUCCESS);
1420 }
1421 
1422 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1423 /*@C
1424   MatSetValues - Inserts or adds a block of values into a matrix.
1425   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1426   MUST be called after all calls to `MatSetValues()` have been completed.
1427 
1428   Not Collective
1429 
1430   Input Parameters:
1431 + mat  - the matrix
1432 . v    - a logically two-dimensional array of values
1433 . m    - the number of rows
1434 . idxm - the global indices of the rows
1435 . n    - the number of columns
1436 . idxn - the global indices of the columns
1437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1438 
1439   Level: beginner
1440 
1441   Notes:
1442   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1443 
1444   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1445   options cannot be mixed without intervening calls to the assembly
1446   routines.
1447 
1448   `MatSetValues()` uses 0-based row and column numbers in Fortran
1449   as well as in C.
1450 
1451   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1452   simply ignored. This allows easily inserting element stiffness matrices
1453   with homogeneous Dirichlet boundary conditions that you don't want represented
1454   in the matrix.
1455 
1456   Efficiency Alert:
1457   The routine `MatSetValuesBlocked()` may offer much better efficiency
1458   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1459 
1460   Developer Notes:
1461   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1462   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1463 
1464 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1465           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1466 @*/
1467 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1468 {
1469   PetscFunctionBeginHot;
1470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1471   PetscValidType(mat, 1);
1472   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1473   PetscAssertPointer(idxm, 3);
1474   PetscAssertPointer(idxn, 5);
1475   MatCheckPreallocated(mat, 1);
1476 
1477   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1478   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1479 
1480   if (PetscDefined(USE_DEBUG)) {
1481     PetscInt i, j;
1482 
1483     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1484     for (i = 0; i < m; i++) {
1485       for (j = 0; j < n; j++) {
1486         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1487 #if defined(PETSC_USE_COMPLEX)
1488           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]);
1489 #else
1490           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]);
1491 #endif
1492       }
1493     }
1494     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);
1495     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);
1496   }
1497 
1498   if (mat->assembled) {
1499     mat->was_assembled = PETSC_TRUE;
1500     mat->assembled     = PETSC_FALSE;
1501   }
1502   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1503   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1504   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1505   PetscFunctionReturn(PETSC_SUCCESS);
1506 }
1507 
1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1509 /*@C
1510   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1511   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1512   MUST be called after all calls to `MatSetValues()` have been completed.
1513 
1514   Not Collective
1515 
1516   Input Parameters:
1517 + mat  - the matrix
1518 . v    - a logically two-dimensional array of values
1519 . ism  - the rows to provide
1520 . isn  - the columns to provide
1521 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1522 
1523   Level: beginner
1524 
1525   Notes:
1526   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1527 
1528   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1529   options cannot be mixed without intervening calls to the assembly
1530   routines.
1531 
1532   `MatSetValues()` uses 0-based row and column numbers in Fortran
1533   as well as in C.
1534 
1535   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1536   simply ignored. This allows easily inserting element stiffness matrices
1537   with homogeneous Dirichlet boundary conditions that you don't want represented
1538   in the matrix.
1539 
1540   Efficiency Alert:
1541   The routine `MatSetValuesBlocked()` may offer much better efficiency
1542   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1543 
1544   This is currently not optimized for any particular `ISType`
1545 
1546   Developer Notes:
1547   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1548   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1549 
1550 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1551           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1552 @*/
1553 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1554 {
1555   PetscInt        m, n;
1556   const PetscInt *rows, *cols;
1557 
1558   PetscFunctionBeginHot;
1559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1560   PetscCall(ISGetIndices(ism, &rows));
1561   PetscCall(ISGetIndices(isn, &cols));
1562   PetscCall(ISGetLocalSize(ism, &m));
1563   PetscCall(ISGetLocalSize(isn, &n));
1564   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1565   PetscCall(ISRestoreIndices(ism, &rows));
1566   PetscCall(ISRestoreIndices(isn, &cols));
1567   PetscFunctionReturn(PETSC_SUCCESS);
1568 }
1569 
1570 /*@
1571   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1572   values into a matrix
1573 
1574   Not Collective
1575 
1576   Input Parameters:
1577 + mat - the matrix
1578 . row - the (block) row to set
1579 - v   - a logically two-dimensional array of values
1580 
1581   Level: intermediate
1582 
1583   Notes:
1584   The values, `v`, are column-oriented (for the block version) and sorted
1585 
1586   All the nonzeros in the row must be provided
1587 
1588   The matrix must have previously had its column indices set, likely by having been assembled.
1589 
1590   The row must belong to this process
1591 
1592 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1593           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1594 @*/
1595 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1596 {
1597   PetscInt globalrow;
1598 
1599   PetscFunctionBegin;
1600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1601   PetscValidType(mat, 1);
1602   PetscAssertPointer(v, 3);
1603   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1604   PetscCall(MatSetValuesRow(mat, globalrow, v));
1605   PetscFunctionReturn(PETSC_SUCCESS);
1606 }
1607 
1608 /*@
1609   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1610   values into a matrix
1611 
1612   Not Collective
1613 
1614   Input Parameters:
1615 + mat - the matrix
1616 . row - the (block) row to set
1617 - 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
1618 
1619   Level: advanced
1620 
1621   Notes:
1622   The values, `v`, are column-oriented for the block version.
1623 
1624   All the nonzeros in the row must be provided
1625 
1626   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1627 
1628   The row must belong to this process
1629 
1630 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1631           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1632 @*/
1633 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1634 {
1635   PetscFunctionBeginHot;
1636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1637   PetscValidType(mat, 1);
1638   MatCheckPreallocated(mat, 1);
1639   PetscAssertPointer(v, 3);
1640   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1641   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1642   mat->insertmode = INSERT_VALUES;
1643 
1644   if (mat->assembled) {
1645     mat->was_assembled = PETSC_TRUE;
1646     mat->assembled     = PETSC_FALSE;
1647   }
1648   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1649   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1650   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1651   PetscFunctionReturn(PETSC_SUCCESS);
1652 }
1653 
1654 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1655 /*@
1656   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1657   Using structured grid indexing
1658 
1659   Not Collective
1660 
1661   Input Parameters:
1662 + mat  - the matrix
1663 . m    - number of rows being entered
1664 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1665 . n    - number of columns being entered
1666 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1667 . v    - a logically two-dimensional array of values
1668 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1669 
1670   Level: beginner
1671 
1672   Notes:
1673   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1674 
1675   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1676   options cannot be mixed without intervening calls to the assembly
1677   routines.
1678 
1679   The grid coordinates are across the entire grid, not just the local portion
1680 
1681   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1682   as well as in C.
1683 
1684   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1685 
1686   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1687   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1688 
1689   The columns and rows in the stencil passed in MUST be contained within the
1690   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1691   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1692   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1693   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1694 
1695   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1696   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1697   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1698   `DM_BOUNDARY_PERIODIC` boundary type.
1699 
1700   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
1701   a single value per point) you can skip filling those indices.
1702 
1703   Inspired by the structured grid interface to the HYPRE package
1704   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1705 
1706   Efficiency Alert:
1707   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1708   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1709 
1710   Fortran Notes:
1711   `idxm` and `idxn` should be declared as
1712 $     MatStencil idxm(4,m),idxn(4,n)
1713   and the values inserted using
1714 .vb
1715     idxm(MatStencil_i,1) = i
1716     idxm(MatStencil_j,1) = j
1717     idxm(MatStencil_k,1) = k
1718     idxm(MatStencil_c,1) = c
1719     etc
1720 .ve
1721 
1722 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1723           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1724 @*/
1725 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1726 {
1727   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1728   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1729   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1730 
1731   PetscFunctionBegin;
1732   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1734   PetscValidType(mat, 1);
1735   PetscAssertPointer(idxm, 3);
1736   PetscAssertPointer(idxn, 5);
1737 
1738   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1739     jdxm = buf;
1740     jdxn = buf + m;
1741   } else {
1742     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1743     jdxm = bufm;
1744     jdxn = bufn;
1745   }
1746   for (i = 0; i < m; i++) {
1747     for (j = 0; j < 3 - sdim; j++) dxm++;
1748     tmp = *dxm++ - starts[0];
1749     for (j = 0; j < dim - 1; j++) {
1750       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1751       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1752     }
1753     if (mat->stencil.noc) dxm++;
1754     jdxm[i] = tmp;
1755   }
1756   for (i = 0; i < n; i++) {
1757     for (j = 0; j < 3 - sdim; j++) dxn++;
1758     tmp = *dxn++ - starts[0];
1759     for (j = 0; j < dim - 1; j++) {
1760       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1761       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1762     }
1763     if (mat->stencil.noc) dxn++;
1764     jdxn[i] = tmp;
1765   }
1766   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1767   PetscCall(PetscFree2(bufm, bufn));
1768   PetscFunctionReturn(PETSC_SUCCESS);
1769 }
1770 
1771 /*@
1772   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1773   Using structured grid indexing
1774 
1775   Not Collective
1776 
1777   Input Parameters:
1778 + mat  - the matrix
1779 . m    - number of rows being entered
1780 . idxm - grid coordinates for matrix rows being entered
1781 . n    - number of columns being entered
1782 . idxn - grid coordinates for matrix columns being entered
1783 . v    - a logically two-dimensional array of values
1784 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1785 
1786   Level: beginner
1787 
1788   Notes:
1789   By default the values, `v`, are row-oriented and unsorted.
1790   See `MatSetOption()` for other options.
1791 
1792   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1793   options cannot be mixed without intervening calls to the assembly
1794   routines.
1795 
1796   The grid coordinates are across the entire grid, not just the local portion
1797 
1798   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1799   as well as in C.
1800 
1801   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1802 
1803   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1804   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1805 
1806   The columns and rows in the stencil passed in MUST be contained within the
1807   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1808   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1809   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1810   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1811 
1812   Negative indices may be passed in idxm and idxn, these rows and columns are
1813   simply ignored. This allows easily inserting element stiffness matrices
1814   with homogeneous Dirichlet boundary conditions that you don't want represented
1815   in the matrix.
1816 
1817   Inspired by the structured grid interface to the HYPRE package
1818   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1819 
1820   Fortran Notes:
1821   `idxm` and `idxn` should be declared as
1822 $     MatStencil idxm(4,m),idxn(4,n)
1823   and the values inserted using
1824 .vb
1825     idxm(MatStencil_i,1) = i
1826     idxm(MatStencil_j,1) = j
1827     idxm(MatStencil_k,1) = k
1828    etc
1829 .ve
1830 
1831 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1832           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1833           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1834 @*/
1835 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1836 {
1837   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1838   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1839   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1840 
1841   PetscFunctionBegin;
1842   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1844   PetscValidType(mat, 1);
1845   PetscAssertPointer(idxm, 3);
1846   PetscAssertPointer(idxn, 5);
1847   PetscAssertPointer(v, 6);
1848 
1849   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1850     jdxm = buf;
1851     jdxn = buf + m;
1852   } else {
1853     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1854     jdxm = bufm;
1855     jdxn = bufn;
1856   }
1857   for (i = 0; i < m; i++) {
1858     for (j = 0; j < 3 - sdim; j++) dxm++;
1859     tmp = *dxm++ - starts[0];
1860     for (j = 0; j < sdim - 1; j++) {
1861       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1862       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1863     }
1864     dxm++;
1865     jdxm[i] = tmp;
1866   }
1867   for (i = 0; i < n; i++) {
1868     for (j = 0; j < 3 - sdim; j++) dxn++;
1869     tmp = *dxn++ - starts[0];
1870     for (j = 0; j < sdim - 1; j++) {
1871       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1872       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1873     }
1874     dxn++;
1875     jdxn[i] = tmp;
1876   }
1877   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1878   PetscCall(PetscFree2(bufm, bufn));
1879   PetscFunctionReturn(PETSC_SUCCESS);
1880 }
1881 
1882 /*@
1883   MatSetStencil - Sets the grid information for setting values into a matrix via
1884   `MatSetValuesStencil()`
1885 
1886   Not Collective
1887 
1888   Input Parameters:
1889 + mat    - the matrix
1890 . dim    - dimension of the grid 1, 2, or 3
1891 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1892 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1893 - dof    - number of degrees of freedom per node
1894 
1895   Level: beginner
1896 
1897   Notes:
1898   Inspired by the structured grid interface to the HYPRE package
1899   (www.llnl.gov/CASC/hyper)
1900 
1901   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1902   user.
1903 
1904 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1905           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1906 @*/
1907 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1908 {
1909   PetscFunctionBegin;
1910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1911   PetscAssertPointer(dims, 3);
1912   PetscAssertPointer(starts, 4);
1913 
1914   mat->stencil.dim = dim + (dof > 1);
1915   for (PetscInt i = 0; i < dim; i++) {
1916     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1917     mat->stencil.starts[i] = starts[dim - i - 1];
1918   }
1919   mat->stencil.dims[dim]   = dof;
1920   mat->stencil.starts[dim] = 0;
1921   mat->stencil.noc         = (PetscBool)(dof == 1);
1922   PetscFunctionReturn(PETSC_SUCCESS);
1923 }
1924 
1925 /*@C
1926   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1927 
1928   Not Collective
1929 
1930   Input Parameters:
1931 + mat  - the matrix
1932 . v    - a logically two-dimensional array of values
1933 . m    - the number of block rows
1934 . idxm - the global block indices
1935 . n    - the number of block columns
1936 . idxn - the global block indices
1937 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1938 
1939   Level: intermediate
1940 
1941   Notes:
1942   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1943   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1944 
1945   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1946   NOT the total number of rows/columns; for example, if the block size is 2 and
1947   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1948   The values in idxm would be 1 2; that is the first index for each block divided by
1949   the block size.
1950 
1951   You must call `MatSetBlockSize()` when constructing this matrix (before
1952   preallocating it).
1953 
1954   By default the values, `v`, are row-oriented, so the layout of
1955   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1956 
1957   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1958   options cannot be mixed without intervening calls to the assembly
1959   routines.
1960 
1961   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1962   as well as in C.
1963 
1964   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1965   simply ignored. This allows easily inserting element stiffness matrices
1966   with homogeneous Dirichlet boundary conditions that you don't want represented
1967   in the matrix.
1968 
1969   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1970   internal searching must be done to determine where to place the
1971   data in the matrix storage space.  By instead inserting blocks of
1972   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1973   reduced.
1974 
1975   Example:
1976 .vb
1977    Suppose m=n=2 and block size(bs) = 2 The array is
1978 
1979    1  2  | 3  4
1980    5  6  | 7  8
1981    - - - | - - -
1982    9  10 | 11 12
1983    13 14 | 15 16
1984 
1985    v[] should be passed in like
1986    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1987 
1988   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1989    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1990 .ve
1991 
1992 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1993 @*/
1994 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1995 {
1996   PetscFunctionBeginHot;
1997   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1998   PetscValidType(mat, 1);
1999   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2000   PetscAssertPointer(idxm, 3);
2001   PetscAssertPointer(idxn, 5);
2002   MatCheckPreallocated(mat, 1);
2003   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2004   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2005   if (PetscDefined(USE_DEBUG)) {
2006     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2007     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2008   }
2009   if (PetscDefined(USE_DEBUG)) {
2010     PetscInt rbs, cbs, M, N, i;
2011     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2012     PetscCall(MatGetSize(mat, &M, &N));
2013     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);
2014     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);
2015   }
2016   if (mat->assembled) {
2017     mat->was_assembled = PETSC_TRUE;
2018     mat->assembled     = PETSC_FALSE;
2019   }
2020   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2021   if (mat->ops->setvaluesblocked) {
2022     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2023   } else {
2024     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2025     PetscInt i, j, bs, cbs;
2026 
2027     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2028     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2029       iidxm = buf;
2030       iidxn = buf + m * bs;
2031     } else {
2032       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2033       iidxm = bufr;
2034       iidxn = bufc;
2035     }
2036     for (i = 0; i < m; i++) {
2037       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2038     }
2039     if (m != n || bs != cbs || idxm != idxn) {
2040       for (i = 0; i < n; i++) {
2041         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2042       }
2043     } else iidxn = iidxm;
2044     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2045     PetscCall(PetscFree2(bufr, bufc));
2046   }
2047   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2048   PetscFunctionReturn(PETSC_SUCCESS);
2049 }
2050 
2051 /*@C
2052   MatGetValues - Gets a block of local values from a matrix.
2053 
2054   Not Collective; can only return values that are owned by the give process
2055 
2056   Input Parameters:
2057 + mat  - the matrix
2058 . v    - a logically two-dimensional array for storing the values
2059 . m    - the number of rows
2060 . idxm - the  global indices of the rows
2061 . n    - the number of columns
2062 - idxn - the global indices of the columns
2063 
2064   Level: advanced
2065 
2066   Notes:
2067   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2068   The values, `v`, are then returned in a row-oriented format,
2069   analogous to that used by default in `MatSetValues()`.
2070 
2071   `MatGetValues()` uses 0-based row and column numbers in
2072   Fortran as well as in C.
2073 
2074   `MatGetValues()` requires that the matrix has been assembled
2075   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2076   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2077   without intermediate matrix assembly.
2078 
2079   Negative row or column indices will be ignored and those locations in `v` will be
2080   left unchanged.
2081 
2082   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2083   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2084   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2085 
2086 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2087 @*/
2088 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2089 {
2090   PetscFunctionBegin;
2091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2092   PetscValidType(mat, 1);
2093   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2094   PetscAssertPointer(idxm, 3);
2095   PetscAssertPointer(idxn, 5);
2096   PetscAssertPointer(v, 6);
2097   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2098   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2099   MatCheckPreallocated(mat, 1);
2100 
2101   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2102   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2103   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2104   PetscFunctionReturn(PETSC_SUCCESS);
2105 }
2106 
2107 /*@C
2108   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2109   defined previously by `MatSetLocalToGlobalMapping()`
2110 
2111   Not Collective
2112 
2113   Input Parameters:
2114 + mat  - the matrix
2115 . nrow - number of rows
2116 . irow - the row local indices
2117 . ncol - number of columns
2118 - icol - the column local indices
2119 
2120   Output Parameter:
2121 . y - a logically two-dimensional array of values
2122 
2123   Level: advanced
2124 
2125   Notes:
2126   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2127 
2128   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,
2129   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2130   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2131   with `MatSetLocalToGlobalMapping()`.
2132 
2133   Developer Notes:
2134   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2135   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2136 
2137 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2138           `MatSetValuesLocal()`, `MatGetValues()`
2139 @*/
2140 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2141 {
2142   PetscFunctionBeginHot;
2143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2144   PetscValidType(mat, 1);
2145   MatCheckPreallocated(mat, 1);
2146   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2147   PetscAssertPointer(irow, 3);
2148   PetscAssertPointer(icol, 5);
2149   if (PetscDefined(USE_DEBUG)) {
2150     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2151     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2152   }
2153   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2154   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2155   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2156   else {
2157     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2158     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2159       irowm = buf;
2160       icolm = buf + nrow;
2161     } else {
2162       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2163       irowm = bufr;
2164       icolm = bufc;
2165     }
2166     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2167     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2168     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2169     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2170     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2171     PetscCall(PetscFree2(bufr, bufc));
2172   }
2173   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2174   PetscFunctionReturn(PETSC_SUCCESS);
2175 }
2176 
2177 /*@
2178   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2179   the same size. Currently, this can only be called once and creates the given matrix.
2180 
2181   Not Collective
2182 
2183   Input Parameters:
2184 + mat  - the matrix
2185 . nb   - the number of blocks
2186 . bs   - the number of rows (and columns) in each block
2187 . rows - a concatenation of the rows for each block
2188 - v    - a concatenation of logically two-dimensional arrays of values
2189 
2190   Level: advanced
2191 
2192   Note:
2193   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2194 
2195   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2196 
2197 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2198           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2199 @*/
2200 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2201 {
2202   PetscFunctionBegin;
2203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2204   PetscValidType(mat, 1);
2205   PetscAssertPointer(rows, 4);
2206   PetscAssertPointer(v, 5);
2207   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2208 
2209   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2210   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2211   else {
2212     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2213   }
2214   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2215   PetscFunctionReturn(PETSC_SUCCESS);
2216 }
2217 
2218 /*@
2219   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2220   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2221   using a local (per-processor) numbering.
2222 
2223   Not Collective
2224 
2225   Input Parameters:
2226 + x        - the matrix
2227 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2228 - cmapping - column mapping
2229 
2230   Level: intermediate
2231 
2232   Note:
2233   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2234 
2235 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2236 @*/
2237 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2241   PetscValidType(x, 1);
2242   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2243   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2244   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2245   else {
2246     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2247     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2248   }
2249   PetscFunctionReturn(PETSC_SUCCESS);
2250 }
2251 
2252 /*@
2253   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2254 
2255   Not Collective
2256 
2257   Input Parameter:
2258 . A - the matrix
2259 
2260   Output Parameters:
2261 + rmapping - row mapping
2262 - cmapping - column mapping
2263 
2264   Level: advanced
2265 
2266 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2267 @*/
2268 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2269 {
2270   PetscFunctionBegin;
2271   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2272   PetscValidType(A, 1);
2273   if (rmapping) {
2274     PetscAssertPointer(rmapping, 2);
2275     *rmapping = A->rmap->mapping;
2276   }
2277   if (cmapping) {
2278     PetscAssertPointer(cmapping, 3);
2279     *cmapping = A->cmap->mapping;
2280   }
2281   PetscFunctionReturn(PETSC_SUCCESS);
2282 }
2283 
2284 /*@
2285   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2286 
2287   Logically Collective
2288 
2289   Input Parameters:
2290 + A    - the matrix
2291 . rmap - row layout
2292 - cmap - column layout
2293 
2294   Level: advanced
2295 
2296   Note:
2297   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2298 
2299 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2300 @*/
2301 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2302 {
2303   PetscFunctionBegin;
2304   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2305   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2306   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2307   PetscFunctionReturn(PETSC_SUCCESS);
2308 }
2309 
2310 /*@
2311   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2312 
2313   Not Collective
2314 
2315   Input Parameter:
2316 . A - the matrix
2317 
2318   Output Parameters:
2319 + rmap - row layout
2320 - cmap - column layout
2321 
2322   Level: advanced
2323 
2324 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2325 @*/
2326 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2327 {
2328   PetscFunctionBegin;
2329   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2330   PetscValidType(A, 1);
2331   if (rmap) {
2332     PetscAssertPointer(rmap, 2);
2333     *rmap = A->rmap;
2334   }
2335   if (cmap) {
2336     PetscAssertPointer(cmap, 3);
2337     *cmap = A->cmap;
2338   }
2339   PetscFunctionReturn(PETSC_SUCCESS);
2340 }
2341 
2342 /*@C
2343   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2344   using a local numbering of the nodes.
2345 
2346   Not Collective
2347 
2348   Input Parameters:
2349 + mat  - the matrix
2350 . nrow - number of rows
2351 . irow - the row local indices
2352 . ncol - number of columns
2353 . icol - the column local indices
2354 . y    - a logically two-dimensional array of values
2355 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2356 
2357   Level: intermediate
2358 
2359   Notes:
2360   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2361   `MatSetUp()` before using this routine
2362 
2363   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2364 
2365   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2366   options cannot be mixed without intervening calls to the assembly
2367   routines.
2368 
2369   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2370   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2371 
2372   Developer Notes:
2373   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2374   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2375 
2376 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2377           `MatGetValuesLocal()`
2378 @*/
2379 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2380 {
2381   PetscFunctionBeginHot;
2382   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2383   PetscValidType(mat, 1);
2384   MatCheckPreallocated(mat, 1);
2385   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2386   PetscAssertPointer(irow, 3);
2387   PetscAssertPointer(icol, 5);
2388   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2389   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2390   if (PetscDefined(USE_DEBUG)) {
2391     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2392     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2393   }
2394 
2395   if (mat->assembled) {
2396     mat->was_assembled = PETSC_TRUE;
2397     mat->assembled     = PETSC_FALSE;
2398   }
2399   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2400   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2401   else {
2402     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2403     const PetscInt *irowm, *icolm;
2404 
2405     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2406       bufr  = buf;
2407       bufc  = buf + nrow;
2408       irowm = bufr;
2409       icolm = bufc;
2410     } else {
2411       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2412       irowm = bufr;
2413       icolm = bufc;
2414     }
2415     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2416     else irowm = irow;
2417     if (mat->cmap->mapping) {
2418       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2419         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2420       } else icolm = irowm;
2421     } else icolm = icol;
2422     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2423     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2424   }
2425   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2426   PetscFunctionReturn(PETSC_SUCCESS);
2427 }
2428 
2429 /*@C
2430   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2431   using a local ordering of the nodes a block at a time.
2432 
2433   Not Collective
2434 
2435   Input Parameters:
2436 + mat  - the matrix
2437 . nrow - number of rows
2438 . irow - the row local indices
2439 . ncol - number of columns
2440 . icol - the column local indices
2441 . y    - a logically two-dimensional array of values
2442 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2443 
2444   Level: intermediate
2445 
2446   Notes:
2447   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2448   `MatSetUp()` before using this routine
2449 
2450   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2451   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2452 
2453   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2454   options cannot be mixed without intervening calls to the assembly
2455   routines.
2456 
2457   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2458   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2459 
2460   Developer Notes:
2461   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2462   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2463 
2464 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2465           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2466 @*/
2467 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2468 {
2469   PetscFunctionBeginHot;
2470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2471   PetscValidType(mat, 1);
2472   MatCheckPreallocated(mat, 1);
2473   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2474   PetscAssertPointer(irow, 3);
2475   PetscAssertPointer(icol, 5);
2476   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2477   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2478   if (PetscDefined(USE_DEBUG)) {
2479     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2480     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);
2481   }
2482 
2483   if (mat->assembled) {
2484     mat->was_assembled = PETSC_TRUE;
2485     mat->assembled     = PETSC_FALSE;
2486   }
2487   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2488     PetscInt irbs, rbs;
2489     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2490     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2491     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2492   }
2493   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2494     PetscInt icbs, cbs;
2495     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2496     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2497     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2498   }
2499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2500   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2501   else {
2502     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2503     const PetscInt *irowm, *icolm;
2504 
2505     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2506       bufr  = buf;
2507       bufc  = buf + nrow;
2508       irowm = bufr;
2509       icolm = bufc;
2510     } else {
2511       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2512       irowm = bufr;
2513       icolm = bufc;
2514     }
2515     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2516     else irowm = irow;
2517     if (mat->cmap->mapping) {
2518       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2519         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2520       } else icolm = irowm;
2521     } else icolm = icol;
2522     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2523     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2524   }
2525   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2526   PetscFunctionReturn(PETSC_SUCCESS);
2527 }
2528 
2529 /*@
2530   MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2531 
2532   Collective
2533 
2534   Input Parameters:
2535 + mat - the matrix
2536 - x   - the vector to be multiplied
2537 
2538   Output Parameter:
2539 . y - the result
2540 
2541   Level: developer
2542 
2543   Note:
2544   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2545   call `MatMultDiagonalBlock`(A,y,y).
2546 
2547 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2548 @*/
2549 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2550 {
2551   PetscFunctionBegin;
2552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2553   PetscValidType(mat, 1);
2554   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2555   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2556 
2557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2559   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2560   MatCheckPreallocated(mat, 1);
2561 
2562   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2563   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2564   PetscFunctionReturn(PETSC_SUCCESS);
2565 }
2566 
2567 /*@
2568   MatMult - Computes the matrix-vector product, y = Ax.
2569 
2570   Neighbor-wise Collective
2571 
2572   Input Parameters:
2573 + mat - the matrix
2574 - x   - the vector to be multiplied
2575 
2576   Output Parameter:
2577 . y - the result
2578 
2579   Level: beginner
2580 
2581   Note:
2582   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2583   call `MatMult`(A,y,y).
2584 
2585 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2586 @*/
2587 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2588 {
2589   PetscFunctionBegin;
2590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2591   PetscValidType(mat, 1);
2592   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2593   VecCheckAssembled(x);
2594   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2597   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2598   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);
2599   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);
2600   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);
2601   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);
2602   PetscCall(VecSetErrorIfLocked(y, 3));
2603   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2604   MatCheckPreallocated(mat, 1);
2605 
2606   PetscCall(VecLockReadPush(x));
2607   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2608   PetscUseTypeMethod(mat, mult, x, y);
2609   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2610   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2611   PetscCall(VecLockReadPop(x));
2612   PetscFunctionReturn(PETSC_SUCCESS);
2613 }
2614 
2615 /*@
2616   MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2617 
2618   Neighbor-wise Collective
2619 
2620   Input Parameters:
2621 + mat - the matrix
2622 - x   - the vector to be multiplied
2623 
2624   Output Parameter:
2625 . y - the result
2626 
2627   Level: beginner
2628 
2629   Notes:
2630   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2631   call `MatMultTranspose`(A,y,y).
2632 
2633   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2634   use `MatMultHermitianTranspose()`
2635 
2636 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2637 @*/
2638 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2639 {
2640   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2641 
2642   PetscFunctionBegin;
2643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2644   PetscValidType(mat, 1);
2645   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2646   VecCheckAssembled(x);
2647   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2648 
2649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2651   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2652   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);
2653   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);
2654   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);
2655   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);
2656   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2657   MatCheckPreallocated(mat, 1);
2658 
2659   if (!mat->ops->multtranspose) {
2660     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2661     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);
2662   } else op = mat->ops->multtranspose;
2663   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2664   PetscCall(VecLockReadPush(x));
2665   PetscCall((*op)(mat, x, y));
2666   PetscCall(VecLockReadPop(x));
2667   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2668   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2669   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2670   PetscFunctionReturn(PETSC_SUCCESS);
2671 }
2672 
2673 /*@
2674   MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2675 
2676   Neighbor-wise Collective
2677 
2678   Input Parameters:
2679 + mat - the matrix
2680 - x   - the vector to be multiplied
2681 
2682   Output Parameter:
2683 . y - the result
2684 
2685   Level: beginner
2686 
2687   Notes:
2688   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2689   call `MatMultHermitianTranspose`(A,y,y).
2690 
2691   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2692 
2693   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2694 
2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2696 @*/
2697 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2698 {
2699   PetscFunctionBegin;
2700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2701   PetscValidType(mat, 1);
2702   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2703   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2704 
2705   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2706   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2707   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2708   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);
2709   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);
2710   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);
2711   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);
2712   MatCheckPreallocated(mat, 1);
2713 
2714   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2715 #if defined(PETSC_USE_COMPLEX)
2716   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2717     PetscCall(VecLockReadPush(x));
2718     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2719     else PetscUseTypeMethod(mat, mult, x, y);
2720     PetscCall(VecLockReadPop(x));
2721   } else {
2722     Vec w;
2723     PetscCall(VecDuplicate(x, &w));
2724     PetscCall(VecCopy(x, w));
2725     PetscCall(VecConjugate(w));
2726     PetscCall(MatMultTranspose(mat, w, y));
2727     PetscCall(VecDestroy(&w));
2728     PetscCall(VecConjugate(y));
2729   }
2730   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2731 #else
2732   PetscCall(MatMultTranspose(mat, x, y));
2733 #endif
2734   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2735   PetscFunctionReturn(PETSC_SUCCESS);
2736 }
2737 
2738 /*@
2739   MatMultAdd -  Computes v3 = v2 + A * v1.
2740 
2741   Neighbor-wise Collective
2742 
2743   Input Parameters:
2744 + mat - the matrix
2745 . v1  - the vector to be multiplied by `mat`
2746 - v2  - the vector to be added to the result
2747 
2748   Output Parameter:
2749 . v3 - the result
2750 
2751   Level: beginner
2752 
2753   Note:
2754   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2755   call `MatMultAdd`(A,v1,v2,v1).
2756 
2757 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2758 @*/
2759 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2760 {
2761   PetscFunctionBegin;
2762   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2763   PetscValidType(mat, 1);
2764   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2765   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2766   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2767 
2768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2770   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);
2771   /* 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);
2772      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); */
2773   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);
2774   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);
2775   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2776   MatCheckPreallocated(mat, 1);
2777 
2778   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2779   PetscCall(VecLockReadPush(v1));
2780   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2781   PetscCall(VecLockReadPop(v1));
2782   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2783   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2784   PetscFunctionReturn(PETSC_SUCCESS);
2785 }
2786 
2787 /*@
2788   MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2789 
2790   Neighbor-wise Collective
2791 
2792   Input Parameters:
2793 + mat - the matrix
2794 . v1  - the vector to be multiplied by the transpose of the matrix
2795 - v2  - the vector to be added to the result
2796 
2797   Output Parameter:
2798 . v3 - the result
2799 
2800   Level: beginner
2801 
2802   Note:
2803   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2804   call `MatMultTransposeAdd`(A,v1,v2,v1).
2805 
2806 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2807 @*/
2808 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2809 {
2810   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2811 
2812   PetscFunctionBegin;
2813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2814   PetscValidType(mat, 1);
2815   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2816   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2817   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2818 
2819   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2820   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2821   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);
2822   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);
2823   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);
2824   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2825   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2826   MatCheckPreallocated(mat, 1);
2827 
2828   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2829   PetscCall(VecLockReadPush(v1));
2830   PetscCall((*op)(mat, v1, v2, v3));
2831   PetscCall(VecLockReadPop(v1));
2832   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2833   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2834   PetscFunctionReturn(PETSC_SUCCESS);
2835 }
2836 
2837 /*@
2838   MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2839 
2840   Neighbor-wise Collective
2841 
2842   Input Parameters:
2843 + mat - the matrix
2844 . v1  - the vector to be multiplied by the Hermitian transpose
2845 - v2  - the vector to be added to the result
2846 
2847   Output Parameter:
2848 . v3 - the result
2849 
2850   Level: beginner
2851 
2852   Note:
2853   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2854   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2855 
2856 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2857 @*/
2858 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2859 {
2860   PetscFunctionBegin;
2861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2862   PetscValidType(mat, 1);
2863   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2864   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2865   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2866 
2867   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2869   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2870   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);
2871   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);
2872   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);
2873   MatCheckPreallocated(mat, 1);
2874 
2875   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2876   PetscCall(VecLockReadPush(v1));
2877   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2878   else {
2879     Vec w, z;
2880     PetscCall(VecDuplicate(v1, &w));
2881     PetscCall(VecCopy(v1, w));
2882     PetscCall(VecConjugate(w));
2883     PetscCall(VecDuplicate(v3, &z));
2884     PetscCall(MatMultTranspose(mat, w, z));
2885     PetscCall(VecDestroy(&w));
2886     PetscCall(VecConjugate(z));
2887     if (v2 != v3) {
2888       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2889     } else {
2890       PetscCall(VecAXPY(v3, 1.0, z));
2891     }
2892     PetscCall(VecDestroy(&z));
2893   }
2894   PetscCall(VecLockReadPop(v1));
2895   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2896   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2897   PetscFunctionReturn(PETSC_SUCCESS);
2898 }
2899 
2900 /*@C
2901   MatGetFactorType - gets the type of factorization it is
2902 
2903   Not Collective
2904 
2905   Input Parameter:
2906 . mat - the matrix
2907 
2908   Output Parameter:
2909 . 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`
2910 
2911   Level: intermediate
2912 
2913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2914           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2915 @*/
2916 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2917 {
2918   PetscFunctionBegin;
2919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2920   PetscValidType(mat, 1);
2921   PetscAssertPointer(t, 2);
2922   *t = mat->factortype;
2923   PetscFunctionReturn(PETSC_SUCCESS);
2924 }
2925 
2926 /*@C
2927   MatSetFactorType - sets the type of factorization it is
2928 
2929   Logically Collective
2930 
2931   Input Parameters:
2932 + mat - the matrix
2933 - 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`
2934 
2935   Level: intermediate
2936 
2937 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2938           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2939 @*/
2940 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2941 {
2942   PetscFunctionBegin;
2943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2944   PetscValidType(mat, 1);
2945   mat->factortype = t;
2946   PetscFunctionReturn(PETSC_SUCCESS);
2947 }
2948 
2949 /*@C
2950   MatGetInfo - Returns information about matrix storage (number of
2951   nonzeros, memory, etc.).
2952 
2953   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2954 
2955   Input Parameters:
2956 + mat  - the matrix
2957 - 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)
2958 
2959   Output Parameter:
2960 . info - matrix information context
2961 
2962   Options Database Key:
2963 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2964 
2965   Notes:
2966   The `MatInfo` context contains a variety of matrix data, including
2967   number of nonzeros allocated and used, number of mallocs during
2968   matrix assembly, etc.  Additional information for factored matrices
2969   is provided (such as the fill ratio, number of mallocs during
2970   factorization, etc.).
2971 
2972   Example:
2973   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2974   data within the MatInfo context.  For example,
2975 .vb
2976       MatInfo info;
2977       Mat     A;
2978       double  mal, nz_a, nz_u;
2979 
2980       MatGetInfo(A, MAT_LOCAL, &info);
2981       mal  = info.mallocs;
2982       nz_a = info.nz_allocated;
2983 .ve
2984 
2985   Fortran users should declare info as a double precision
2986   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2987   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2988   a complete list of parameter names.
2989 .vb
2990       double  precision info(MAT_INFO_SIZE)
2991       double  precision mal, nz_a
2992       Mat     A
2993       integer ierr
2994 
2995       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2996       mal = info(MAT_INFO_MALLOCS)
2997       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2998 .ve
2999 
3000   Level: intermediate
3001 
3002   Developer Notes:
3003   The Fortran interface is not autogenerated as the
3004   interface definition cannot be generated correctly [due to `MatInfo` argument]
3005 
3006 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3007 @*/
3008 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3009 {
3010   PetscFunctionBegin;
3011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3012   PetscValidType(mat, 1);
3013   PetscAssertPointer(info, 3);
3014   MatCheckPreallocated(mat, 1);
3015   PetscUseTypeMethod(mat, getinfo, flag, info);
3016   PetscFunctionReturn(PETSC_SUCCESS);
3017 }
3018 
3019 /*
3020    This is used by external packages where it is not easy to get the info from the actual
3021    matrix factorization.
3022 */
3023 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3024 {
3025   PetscFunctionBegin;
3026   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3027   PetscFunctionReturn(PETSC_SUCCESS);
3028 }
3029 
3030 /*@C
3031   MatLUFactor - Performs in-place LU factorization of matrix.
3032 
3033   Collective
3034 
3035   Input Parameters:
3036 + mat  - the matrix
3037 . row  - row permutation
3038 . col  - column permutation
3039 - info - options for factorization, includes
3040 .vb
3041           fill - expected fill as ratio of original fill.
3042           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3043                    Run with the option -info to determine an optimal value to use
3044 .ve
3045 
3046   Level: developer
3047 
3048   Notes:
3049   Most users should employ the `KSP` interface for linear solvers
3050   instead of working directly with matrix algebra routines such as this.
3051   See, e.g., `KSPCreate()`.
3052 
3053   This changes the state of the matrix to a factored matrix; it cannot be used
3054   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3055 
3056   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3057   when not using `KSP`.
3058 
3059   Developer Notes:
3060   The Fortran interface is not autogenerated as the
3061   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3062 
3063 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3064           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3065 @*/
3066 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3067 {
3068   MatFactorInfo tinfo;
3069 
3070   PetscFunctionBegin;
3071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3072   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3073   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3074   if (info) PetscAssertPointer(info, 4);
3075   PetscValidType(mat, 1);
3076   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3077   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3078   MatCheckPreallocated(mat, 1);
3079   if (!info) {
3080     PetscCall(MatFactorInfoInitialize(&tinfo));
3081     info = &tinfo;
3082   }
3083 
3084   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3085   PetscUseTypeMethod(mat, lufactor, row, col, info);
3086   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3087   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3088   PetscFunctionReturn(PETSC_SUCCESS);
3089 }
3090 
3091 /*@C
3092   MatILUFactor - Performs in-place ILU factorization of matrix.
3093 
3094   Collective
3095 
3096   Input Parameters:
3097 + mat  - the matrix
3098 . row  - row permutation
3099 . col  - column permutation
3100 - info - structure containing
3101 .vb
3102       levels - number of levels of fill.
3103       expected fill - as ratio of original fill.
3104       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3105                 missing diagonal entries)
3106 .ve
3107 
3108   Level: developer
3109 
3110   Notes:
3111   Most users should employ the `KSP` interface for linear solvers
3112   instead of working directly with matrix algebra routines such as this.
3113   See, e.g., `KSPCreate()`.
3114 
3115   Probably really in-place only when level of fill is zero, otherwise allocates
3116   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3117   when not using `KSP`.
3118 
3119   Developer Notes:
3120   The Fortran interface is not autogenerated as the
3121   interface definition cannot be generated correctly [due to MatFactorInfo]
3122 
3123 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3124 @*/
3125 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3126 {
3127   PetscFunctionBegin;
3128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3129   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3130   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3131   PetscAssertPointer(info, 4);
3132   PetscValidType(mat, 1);
3133   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3134   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3135   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3136   MatCheckPreallocated(mat, 1);
3137 
3138   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3139   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3140   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3141   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3142   PetscFunctionReturn(PETSC_SUCCESS);
3143 }
3144 
3145 /*@C
3146   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3147   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3148 
3149   Collective
3150 
3151   Input Parameters:
3152 + fact - the factor matrix obtained with `MatGetFactor()`
3153 . mat  - the matrix
3154 . row  - the row permutation
3155 . col  - the column permutation
3156 - info - options for factorization, includes
3157 .vb
3158           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3159           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3160 .ve
3161 
3162   Level: developer
3163 
3164   Notes:
3165   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3166 
3167   Most users should employ the simplified `KSP` interface for linear solvers
3168   instead of working directly with matrix algebra routines such as this.
3169   See, e.g., `KSPCreate()`.
3170 
3171   Developer Notes:
3172   The Fortran interface is not autogenerated as the
3173   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3174 
3175 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3176 @*/
3177 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3178 {
3179   MatFactorInfo tinfo;
3180 
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3184   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3185   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3186   if (info) PetscAssertPointer(info, 5);
3187   PetscValidType(fact, 1);
3188   PetscValidType(mat, 2);
3189   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3191   MatCheckPreallocated(mat, 2);
3192   if (!info) {
3193     PetscCall(MatFactorInfoInitialize(&tinfo));
3194     info = &tinfo;
3195   }
3196 
3197   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3198   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3199   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3200   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3201   PetscFunctionReturn(PETSC_SUCCESS);
3202 }
3203 
3204 /*@C
3205   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3206   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3207 
3208   Collective
3209 
3210   Input Parameters:
3211 + fact - the factor matrix obtained with `MatGetFactor()`
3212 . mat  - the matrix
3213 - info - options for factorization
3214 
3215   Level: developer
3216 
3217   Notes:
3218   See `MatLUFactor()` for in-place factorization.  See
3219   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3220 
3221   Most users should employ the `KSP` interface for linear solvers
3222   instead of working directly with matrix algebra routines such as this.
3223   See, e.g., `KSPCreate()`.
3224 
3225   Developer Notes:
3226   The Fortran interface is not autogenerated as the
3227   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3228 
3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3230 @*/
3231 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3232 {
3233   MatFactorInfo tinfo;
3234 
3235   PetscFunctionBegin;
3236   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3238   PetscValidType(fact, 1);
3239   PetscValidType(mat, 2);
3240   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3241   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,
3242              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3243 
3244   MatCheckPreallocated(mat, 2);
3245   if (!info) {
3246     PetscCall(MatFactorInfoInitialize(&tinfo));
3247     info = &tinfo;
3248   }
3249 
3250   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3251   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3252   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3253   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3254   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3255   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3256   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3257   PetscFunctionReturn(PETSC_SUCCESS);
3258 }
3259 
3260 /*@C
3261   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3262   symmetric matrix.
3263 
3264   Collective
3265 
3266   Input Parameters:
3267 + mat  - the matrix
3268 . perm - row and column permutations
3269 - info - expected fill as ratio of original fill
3270 
3271   Level: developer
3272 
3273   Notes:
3274   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3275   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3276 
3277   Most users should employ the `KSP` interface for linear solvers
3278   instead of working directly with matrix algebra routines such as this.
3279   See, e.g., `KSPCreate()`.
3280 
3281   Developer Notes:
3282   The Fortran interface is not autogenerated as the
3283   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3284 
3285 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3286           `MatGetOrdering()`
3287 @*/
3288 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3289 {
3290   MatFactorInfo tinfo;
3291 
3292   PetscFunctionBegin;
3293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3294   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3295   if (info) PetscAssertPointer(info, 3);
3296   PetscValidType(mat, 1);
3297   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3298   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3300   MatCheckPreallocated(mat, 1);
3301   if (!info) {
3302     PetscCall(MatFactorInfoInitialize(&tinfo));
3303     info = &tinfo;
3304   }
3305 
3306   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3307   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3308   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3309   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3310   PetscFunctionReturn(PETSC_SUCCESS);
3311 }
3312 
3313 /*@C
3314   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3315   of a symmetric matrix.
3316 
3317   Collective
3318 
3319   Input Parameters:
3320 + fact - the factor matrix obtained with `MatGetFactor()`
3321 . mat  - the matrix
3322 . perm - row and column permutations
3323 - info - options for factorization, includes
3324 .vb
3325           fill - expected fill as ratio of original fill.
3326           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3327                    Run with the option -info to determine an optimal value to use
3328 .ve
3329 
3330   Level: developer
3331 
3332   Notes:
3333   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3334   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3335 
3336   Most users should employ the `KSP` interface for linear solvers
3337   instead of working directly with matrix algebra routines such as this.
3338   See, e.g., `KSPCreate()`.
3339 
3340   Developer Notes:
3341   The Fortran interface is not autogenerated as the
3342   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3343 
3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3345           `MatGetOrdering()`
3346 @*/
3347 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3348 {
3349   MatFactorInfo tinfo;
3350 
3351   PetscFunctionBegin;
3352   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3353   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3354   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3355   if (info) PetscAssertPointer(info, 4);
3356   PetscValidType(fact, 1);
3357   PetscValidType(mat, 2);
3358   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3361   MatCheckPreallocated(mat, 2);
3362   if (!info) {
3363     PetscCall(MatFactorInfoInitialize(&tinfo));
3364     info = &tinfo;
3365   }
3366 
3367   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3368   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3370   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3371   PetscFunctionReturn(PETSC_SUCCESS);
3372 }
3373 
3374 /*@C
3375   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3376   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3377   `MatCholeskyFactorSymbolic()`.
3378 
3379   Collective
3380 
3381   Input Parameters:
3382 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3383 . mat  - the initial matrix that is to be factored
3384 - info - options for factorization
3385 
3386   Level: developer
3387 
3388   Note:
3389   Most users should employ the `KSP` interface for linear solvers
3390   instead of working directly with matrix algebra routines such as this.
3391   See, e.g., `KSPCreate()`.
3392 
3393   Developer Notes:
3394   The Fortran interface is not autogenerated as the
3395   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3396 
3397 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3398 @*/
3399 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3400 {
3401   MatFactorInfo tinfo;
3402 
3403   PetscFunctionBegin;
3404   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3406   PetscValidType(fact, 1);
3407   PetscValidType(mat, 2);
3408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3409   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,
3410              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3411   MatCheckPreallocated(mat, 2);
3412   if (!info) {
3413     PetscCall(MatFactorInfoInitialize(&tinfo));
3414     info = &tinfo;
3415   }
3416 
3417   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3418   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3419   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3420   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3421   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3422   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3423   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3424   PetscFunctionReturn(PETSC_SUCCESS);
3425 }
3426 
3427 /*@
3428   MatQRFactor - Performs in-place QR factorization of matrix.
3429 
3430   Collective
3431 
3432   Input Parameters:
3433 + mat  - the matrix
3434 . col  - column permutation
3435 - info - options for factorization, includes
3436 .vb
3437           fill - expected fill as ratio of original fill.
3438           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3439                    Run with the option -info to determine an optimal value to use
3440 .ve
3441 
3442   Level: developer
3443 
3444   Notes:
3445   Most users should employ the `KSP` interface for linear solvers
3446   instead of working directly with matrix algebra routines such as this.
3447   See, e.g., `KSPCreate()`.
3448 
3449   This changes the state of the matrix to a factored matrix; it cannot be used
3450   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3451 
3452   Developer Notes:
3453   The Fortran interface is not autogenerated as the
3454   interface definition cannot be generated correctly [due to MatFactorInfo]
3455 
3456 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3457           `MatSetUnfactored()`
3458 @*/
3459 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3460 {
3461   PetscFunctionBegin;
3462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3463   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3464   if (info) PetscAssertPointer(info, 3);
3465   PetscValidType(mat, 1);
3466   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3467   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3468   MatCheckPreallocated(mat, 1);
3469   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3470   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3471   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3472   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3473   PetscFunctionReturn(PETSC_SUCCESS);
3474 }
3475 
3476 /*@
3477   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3478   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3479 
3480   Collective
3481 
3482   Input Parameters:
3483 + fact - the factor matrix obtained with `MatGetFactor()`
3484 . mat  - the matrix
3485 . col  - column permutation
3486 - info - options for factorization, includes
3487 .vb
3488           fill - expected fill as ratio of original fill.
3489           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3490                    Run with the option -info to determine an optimal value to use
3491 .ve
3492 
3493   Level: developer
3494 
3495   Note:
3496   Most users should employ the `KSP` interface for linear solvers
3497   instead of working directly with matrix algebra routines such as this.
3498   See, e.g., `KSPCreate()`.
3499 
3500   Developer Notes:
3501   The Fortran interface is not autogenerated as the
3502   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3503 
3504 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3505 @*/
3506 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3507 {
3508   MatFactorInfo tinfo;
3509 
3510   PetscFunctionBegin;
3511   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3512   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3513   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3514   if (info) PetscAssertPointer(info, 4);
3515   PetscValidType(fact, 1);
3516   PetscValidType(mat, 2);
3517   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3518   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3519   MatCheckPreallocated(mat, 2);
3520   if (!info) {
3521     PetscCall(MatFactorInfoInitialize(&tinfo));
3522     info = &tinfo;
3523   }
3524 
3525   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3526   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3527   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3528   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3529   PetscFunctionReturn(PETSC_SUCCESS);
3530 }
3531 
3532 /*@
3533   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3534   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3535 
3536   Collective
3537 
3538   Input Parameters:
3539 + fact - the factor matrix obtained with `MatGetFactor()`
3540 . mat  - the matrix
3541 - info - options for factorization
3542 
3543   Level: developer
3544 
3545   Notes:
3546   See `MatQRFactor()` for in-place factorization.
3547 
3548   Most users should employ the `KSP` interface for linear solvers
3549   instead of working directly with matrix algebra routines such as this.
3550   See, e.g., `KSPCreate()`.
3551 
3552   Developer Notes:
3553   The Fortran interface is not autogenerated as the
3554   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3555 
3556 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3557 @*/
3558 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3559 {
3560   MatFactorInfo tinfo;
3561 
3562   PetscFunctionBegin;
3563   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3565   PetscValidType(fact, 1);
3566   PetscValidType(mat, 2);
3567   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3568   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,
3569              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3570 
3571   MatCheckPreallocated(mat, 2);
3572   if (!info) {
3573     PetscCall(MatFactorInfoInitialize(&tinfo));
3574     info = &tinfo;
3575   }
3576 
3577   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3578   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3579   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3580   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3581   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3582   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatSolve - Solves A x = b, given a factored matrix.
3589 
3590   Neighbor-wise Collective
3591 
3592   Input Parameters:
3593 + mat - the factored matrix
3594 - b   - the right-hand-side vector
3595 
3596   Output Parameter:
3597 . x - the result vector
3598 
3599   Level: developer
3600 
3601   Notes:
3602   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3603   call `MatSolve`(A,x,x).
3604 
3605   Most users should employ the `KSP` interface for linear solvers
3606   instead of working directly with matrix algebra routines such as this.
3607   See, e.g., `KSPCreate()`.
3608 
3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3610 @*/
3611 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3612 {
3613   PetscFunctionBegin;
3614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3615   PetscValidType(mat, 1);
3616   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3617   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3618   PetscCheckSameComm(mat, 1, b, 2);
3619   PetscCheckSameComm(mat, 1, x, 3);
3620   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3621   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);
3622   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);
3623   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);
3624   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3625   MatCheckPreallocated(mat, 1);
3626 
3627   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3628   if (mat->factorerrortype) {
3629     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3630     PetscCall(VecSetInf(x));
3631   } else PetscUseTypeMethod(mat, solve, b, x);
3632   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3633   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3634   PetscFunctionReturn(PETSC_SUCCESS);
3635 }
3636 
3637 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3638 {
3639   Vec      b, x;
3640   PetscInt N, i;
3641   PetscErrorCode (*f)(Mat, Vec, Vec);
3642   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3643 
3644   PetscFunctionBegin;
3645   if (A->factorerrortype) {
3646     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3647     PetscCall(MatSetInf(X));
3648     PetscFunctionReturn(PETSC_SUCCESS);
3649   }
3650   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3651   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3652   PetscCall(MatBoundToCPU(A, &Abound));
3653   if (!Abound) {
3654     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3655     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3656   }
3657 #if PetscDefined(HAVE_CUDA)
3658   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3659   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3660 #elif PetscDefined(HAVE_HIP)
3661   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3662   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3663 #endif
3664   PetscCall(MatGetSize(B, NULL, &N));
3665   for (i = 0; i < N; i++) {
3666     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3667     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3668     PetscCall((*f)(A, b, x));
3669     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3670     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3671   }
3672   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3673   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3674   PetscFunctionReturn(PETSC_SUCCESS);
3675 }
3676 
3677 /*@
3678   MatMatSolve - Solves A X = B, given a factored matrix.
3679 
3680   Neighbor-wise Collective
3681 
3682   Input Parameters:
3683 + A - the factored matrix
3684 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3685 
3686   Output Parameter:
3687 . X - the result matrix (dense matrix)
3688 
3689   Level: developer
3690 
3691   Note:
3692   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3693   otherwise, `B` and `X` cannot be the same.
3694 
3695 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3696 @*/
3697 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3698 {
3699   PetscFunctionBegin;
3700   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3701   PetscValidType(A, 1);
3702   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3703   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3704   PetscCheckSameComm(A, 1, B, 2);
3705   PetscCheckSameComm(A, 1, X, 3);
3706   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);
3707   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);
3708   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");
3709   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3710   MatCheckPreallocated(A, 1);
3711 
3712   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3713   if (!A->ops->matsolve) {
3714     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3715     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3716   } else PetscUseTypeMethod(A, matsolve, B, X);
3717   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3718   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3719   PetscFunctionReturn(PETSC_SUCCESS);
3720 }
3721 
3722 /*@
3723   MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3724 
3725   Neighbor-wise Collective
3726 
3727   Input Parameters:
3728 + A - the factored matrix
3729 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3730 
3731   Output Parameter:
3732 . X - the result matrix (dense matrix)
3733 
3734   Level: developer
3735 
3736   Note:
3737   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3738   call `MatMatSolveTranspose`(A,X,X).
3739 
3740 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3741 @*/
3742 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3743 {
3744   PetscFunctionBegin;
3745   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3746   PetscValidType(A, 1);
3747   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3748   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3749   PetscCheckSameComm(A, 1, B, 2);
3750   PetscCheckSameComm(A, 1, X, 3);
3751   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3752   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);
3753   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);
3754   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);
3755   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");
3756   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3757   MatCheckPreallocated(A, 1);
3758 
3759   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3760   if (!A->ops->matsolvetranspose) {
3761     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3762     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3763   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3764   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(PETSC_SUCCESS);
3767 }
3768 
3769 /*@
3770   MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3771 
3772   Neighbor-wise Collective
3773 
3774   Input Parameters:
3775 + A  - the factored matrix
3776 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3777 
3778   Output Parameter:
3779 . X - the result matrix (dense matrix)
3780 
3781   Level: developer
3782 
3783   Note:
3784   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
3785   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3786 
3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3788 @*/
3789 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3790 {
3791   PetscFunctionBegin;
3792   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3793   PetscValidType(A, 1);
3794   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3795   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3796   PetscCheckSameComm(A, 1, Bt, 2);
3797   PetscCheckSameComm(A, 1, X, 3);
3798 
3799   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3800   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);
3801   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);
3802   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");
3803   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3804   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3805   MatCheckPreallocated(A, 1);
3806 
3807   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3808   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3809   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3810   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3811   PetscFunctionReturn(PETSC_SUCCESS);
3812 }
3813 
3814 /*@
3815   MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3816   U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3817 
3818   Neighbor-wise Collective
3819 
3820   Input Parameters:
3821 + mat - the factored matrix
3822 - b   - the right-hand-side vector
3823 
3824   Output Parameter:
3825 . x - the result vector
3826 
3827   Level: developer
3828 
3829   Notes:
3830   `MatSolve()` should be used for most applications, as it performs
3831   a forward solve followed by a backward solve.
3832 
3833   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3834   call `MatForwardSolve`(A,x,x).
3835 
3836   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3837   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3838   `MatForwardSolve()` solves U^T*D y = b, and
3839   `MatBackwardSolve()` solves U x = y.
3840   Thus they do not provide a symmetric preconditioner.
3841 
3842 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3843 @*/
3844 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3845 {
3846   PetscFunctionBegin;
3847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3848   PetscValidType(mat, 1);
3849   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3850   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3851   PetscCheckSameComm(mat, 1, b, 2);
3852   PetscCheckSameComm(mat, 1, x, 3);
3853   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3854   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);
3855   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);
3856   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);
3857   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3858   MatCheckPreallocated(mat, 1);
3859 
3860   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3861   PetscUseTypeMethod(mat, forwardsolve, b, x);
3862   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3863   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3864   PetscFunctionReturn(PETSC_SUCCESS);
3865 }
3866 
3867 /*@
3868   MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3869   D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3870 
3871   Neighbor-wise Collective
3872 
3873   Input Parameters:
3874 + mat - the factored matrix
3875 - b   - the right-hand-side vector
3876 
3877   Output Parameter:
3878 . x - the result vector
3879 
3880   Level: developer
3881 
3882   Notes:
3883   `MatSolve()` should be used for most applications, as it performs
3884   a forward solve followed by a backward solve.
3885 
3886   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3887   call `MatBackwardSolve`(A,x,x).
3888 
3889   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3890   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3891   `MatForwardSolve()` solves U^T*D y = b, and
3892   `MatBackwardSolve()` solves U x = y.
3893   Thus they do not provide a symmetric preconditioner.
3894 
3895 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3896 @*/
3897 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3898 {
3899   PetscFunctionBegin;
3900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3901   PetscValidType(mat, 1);
3902   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3903   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3904   PetscCheckSameComm(mat, 1, b, 2);
3905   PetscCheckSameComm(mat, 1, x, 3);
3906   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3907   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);
3908   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);
3909   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);
3910   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3911   MatCheckPreallocated(mat, 1);
3912 
3913   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3914   PetscUseTypeMethod(mat, backwardsolve, b, x);
3915   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3916   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3917   PetscFunctionReturn(PETSC_SUCCESS);
3918 }
3919 
3920 /*@
3921   MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3922 
3923   Neighbor-wise Collective
3924 
3925   Input Parameters:
3926 + mat - the factored matrix
3927 . b   - the right-hand-side vector
3928 - y   - the vector to be added to
3929 
3930   Output Parameter:
3931 . x - the result vector
3932 
3933   Level: developer
3934 
3935   Note:
3936   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3937   call `MatSolveAdd`(A,x,y,x).
3938 
3939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3940 @*/
3941 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3942 {
3943   PetscScalar one = 1.0;
3944   Vec         tmp;
3945 
3946   PetscFunctionBegin;
3947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3948   PetscValidType(mat, 1);
3949   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3950   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3951   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3952   PetscCheckSameComm(mat, 1, b, 2);
3953   PetscCheckSameComm(mat, 1, y, 3);
3954   PetscCheckSameComm(mat, 1, x, 4);
3955   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3956   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);
3957   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);
3958   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);
3959   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);
3960   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);
3961   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3962   MatCheckPreallocated(mat, 1);
3963 
3964   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3965   if (mat->factorerrortype) {
3966     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3967     PetscCall(VecSetInf(x));
3968   } else if (mat->ops->solveadd) {
3969     PetscUseTypeMethod(mat, solveadd, b, y, x);
3970   } else {
3971     /* do the solve then the add manually */
3972     if (x != y) {
3973       PetscCall(MatSolve(mat, b, x));
3974       PetscCall(VecAXPY(x, one, y));
3975     } else {
3976       PetscCall(VecDuplicate(x, &tmp));
3977       PetscCall(VecCopy(x, tmp));
3978       PetscCall(MatSolve(mat, b, x));
3979       PetscCall(VecAXPY(x, one, tmp));
3980       PetscCall(VecDestroy(&tmp));
3981     }
3982   }
3983   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3984   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3985   PetscFunctionReturn(PETSC_SUCCESS);
3986 }
3987 
3988 /*@
3989   MatSolveTranspose - Solves A' x = b, given a factored matrix.
3990 
3991   Neighbor-wise Collective
3992 
3993   Input Parameters:
3994 + mat - the factored matrix
3995 - b   - the right-hand-side vector
3996 
3997   Output Parameter:
3998 . x - the result vector
3999 
4000   Level: developer
4001 
4002   Notes:
4003   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4004   call `MatSolveTranspose`(A,x,x).
4005 
4006   Most users should employ the `KSP` interface for linear solvers
4007   instead of working directly with matrix algebra routines such as this.
4008   See, e.g., `KSPCreate()`.
4009 
4010 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4011 @*/
4012 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4013 {
4014   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4015 
4016   PetscFunctionBegin;
4017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4018   PetscValidType(mat, 1);
4019   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4020   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4021   PetscCheckSameComm(mat, 1, b, 2);
4022   PetscCheckSameComm(mat, 1, x, 3);
4023   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4024   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);
4025   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);
4026   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4027   MatCheckPreallocated(mat, 1);
4028   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4029   if (mat->factorerrortype) {
4030     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4031     PetscCall(VecSetInf(x));
4032   } else {
4033     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4034     PetscCall((*f)(mat, b, x));
4035   }
4036   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4037   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4038   PetscFunctionReturn(PETSC_SUCCESS);
4039 }
4040 
4041 /*@
4042   MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4043   factored matrix.
4044 
4045   Neighbor-wise Collective
4046 
4047   Input Parameters:
4048 + mat - the factored matrix
4049 . b   - the right-hand-side vector
4050 - y   - the vector to be added to
4051 
4052   Output Parameter:
4053 . x - the result vector
4054 
4055   Level: developer
4056 
4057   Note:
4058   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4059   call `MatSolveTransposeAdd`(A,x,y,x).
4060 
4061 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4062 @*/
4063 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4064 {
4065   PetscScalar one = 1.0;
4066   Vec         tmp;
4067   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4068 
4069   PetscFunctionBegin;
4070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4071   PetscValidType(mat, 1);
4072   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4073   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4074   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4075   PetscCheckSameComm(mat, 1, b, 2);
4076   PetscCheckSameComm(mat, 1, y, 3);
4077   PetscCheckSameComm(mat, 1, x, 4);
4078   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4079   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);
4080   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);
4081   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);
4082   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);
4083   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4084   MatCheckPreallocated(mat, 1);
4085 
4086   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4087   if (mat->factorerrortype) {
4088     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4089     PetscCall(VecSetInf(x));
4090   } else if (f) {
4091     PetscCall((*f)(mat, b, y, x));
4092   } else {
4093     /* do the solve then the add manually */
4094     if (x != y) {
4095       PetscCall(MatSolveTranspose(mat, b, x));
4096       PetscCall(VecAXPY(x, one, y));
4097     } else {
4098       PetscCall(VecDuplicate(x, &tmp));
4099       PetscCall(VecCopy(x, tmp));
4100       PetscCall(MatSolveTranspose(mat, b, x));
4101       PetscCall(VecAXPY(x, one, tmp));
4102       PetscCall(VecDestroy(&tmp));
4103     }
4104   }
4105   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4106   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4107   PetscFunctionReturn(PETSC_SUCCESS);
4108 }
4109 
4110 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4111 /*@
4112   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4113 
4114   Neighbor-wise Collective
4115 
4116   Input Parameters:
4117 + mat   - the matrix
4118 . b     - the right hand side
4119 . omega - the relaxation factor
4120 . flag  - flag indicating the type of SOR (see below)
4121 . shift - diagonal shift
4122 . its   - the number of iterations
4123 - lits  - the number of local iterations
4124 
4125   Output Parameter:
4126 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4127 
4128   SOR Flags:
4129 +     `SOR_FORWARD_SWEEP` - forward SOR
4130 .     `SOR_BACKWARD_SWEEP` - backward SOR
4131 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4132 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4133 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4134 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4135 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4136 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4137   upper/lower triangular part of matrix to
4138   vector (with omega)
4139 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4140 
4141   Level: developer
4142 
4143   Notes:
4144   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4145   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4146   on each processor.
4147 
4148   Application programmers will not generally use `MatSOR()` directly,
4149   but instead will employ the `KSP`/`PC` interface.
4150 
4151   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4152 
4153   Most users should employ the `KSP` interface for linear solvers
4154   instead of working directly with matrix algebra routines such as this.
4155   See, e.g., `KSPCreate()`.
4156 
4157   Vectors `x` and `b` CANNOT be the same
4158 
4159   The flags are implemented as bitwise inclusive or operations.
4160   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4161   to specify a zero initial guess for SSOR.
4162 
4163   Developer Notes:
4164   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4165 
4166 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4167 @*/
4168 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4169 {
4170   PetscFunctionBegin;
4171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4172   PetscValidType(mat, 1);
4173   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4174   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4175   PetscCheckSameComm(mat, 1, b, 2);
4176   PetscCheckSameComm(mat, 1, x, 8);
4177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4179   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);
4180   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);
4181   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);
4182   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4183   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4184   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4185 
4186   MatCheckPreallocated(mat, 1);
4187   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4188   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4189   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4190   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4191   PetscFunctionReturn(PETSC_SUCCESS);
4192 }
4193 
4194 /*
4195       Default matrix copy routine.
4196 */
4197 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4198 {
4199   PetscInt           i, rstart = 0, rend = 0, nz;
4200   const PetscInt    *cwork;
4201   const PetscScalar *vwork;
4202 
4203   PetscFunctionBegin;
4204   if (B->assembled) PetscCall(MatZeroEntries(B));
4205   if (str == SAME_NONZERO_PATTERN) {
4206     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4207     for (i = rstart; i < rend; i++) {
4208       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4209       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4210       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4211     }
4212   } else {
4213     PetscCall(MatAYPX(B, 0.0, A, str));
4214   }
4215   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4216   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4217   PetscFunctionReturn(PETSC_SUCCESS);
4218 }
4219 
4220 /*@
4221   MatCopy - Copies a matrix to another matrix.
4222 
4223   Collective
4224 
4225   Input Parameters:
4226 + A   - the matrix
4227 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4228 
4229   Output Parameter:
4230 . B - where the copy is put
4231 
4232   Level: intermediate
4233 
4234   Notes:
4235   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4236 
4237   `MatCopy()` copies the matrix entries of a matrix to another existing
4238   matrix (after first zeroing the second matrix).  A related routine is
4239   `MatConvert()`, which first creates a new matrix and then copies the data.
4240 
4241 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4242 @*/
4243 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4244 {
4245   PetscInt i;
4246 
4247   PetscFunctionBegin;
4248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4249   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4250   PetscValidType(A, 1);
4251   PetscValidType(B, 2);
4252   PetscCheckSameComm(A, 1, B, 2);
4253   MatCheckPreallocated(B, 2);
4254   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4255   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4256   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,
4257              A->cmap->N, B->cmap->N);
4258   MatCheckPreallocated(A, 1);
4259   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4260 
4261   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4262   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4263   else PetscCall(MatCopy_Basic(A, B, str));
4264 
4265   B->stencil.dim = A->stencil.dim;
4266   B->stencil.noc = A->stencil.noc;
4267   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4268     B->stencil.dims[i]   = A->stencil.dims[i];
4269     B->stencil.starts[i] = A->stencil.starts[i];
4270   }
4271 
4272   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4273   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4274   PetscFunctionReturn(PETSC_SUCCESS);
4275 }
4276 
4277 /*@C
4278   MatConvert - Converts a matrix to another matrix, either of the same
4279   or different type.
4280 
4281   Collective
4282 
4283   Input Parameters:
4284 + mat     - the matrix
4285 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4286    same type as the original matrix.
4287 - reuse   - denotes if the destination matrix is to be created or reused.
4288    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
4289    `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).
4290 
4291   Output Parameter:
4292 . M - pointer to place new matrix
4293 
4294   Level: intermediate
4295 
4296   Notes:
4297   `MatConvert()` first creates a new matrix and then copies the data from
4298   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4299   entries of one matrix to another already existing matrix context.
4300 
4301   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4302   the MPI communicator of the generated matrix is always the same as the communicator
4303   of the input matrix.
4304 
4305 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4306 @*/
4307 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4308 {
4309   PetscBool  sametype, issame, flg;
4310   PetscBool3 issymmetric, ishermitian;
4311   char       convname[256], mtype[256];
4312   Mat        B;
4313 
4314   PetscFunctionBegin;
4315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4316   PetscValidType(mat, 1);
4317   PetscAssertPointer(M, 4);
4318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4320   MatCheckPreallocated(mat, 1);
4321 
4322   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4323   if (flg) newtype = mtype;
4324 
4325   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4326   PetscCall(PetscStrcmp(newtype, "same", &issame));
4327   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4328   if (reuse == MAT_REUSE_MATRIX) {
4329     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4330     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4331   }
4332 
4333   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4334     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4335     PetscFunctionReturn(PETSC_SUCCESS);
4336   }
4337 
4338   /* Cache Mat options because some converters use MatHeaderReplace  */
4339   issymmetric = mat->symmetric;
4340   ishermitian = mat->hermitian;
4341 
4342   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4343     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4344     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345   } else {
4346     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4347     const char *prefix[3]                                 = {"seq", "mpi", ""};
4348     PetscInt    i;
4349     /*
4350        Order of precedence:
4351        0) See if newtype is a superclass of the current matrix.
4352        1) See if a specialized converter is known to the current matrix.
4353        2) See if a specialized converter is known to the desired matrix class.
4354        3) See if a good general converter is registered for the desired class
4355           (as of 6/27/03 only MATMPIADJ falls into this category).
4356        4) See if a good general converter is known for the current matrix.
4357        5) Use a really basic converter.
4358     */
4359 
4360     /* 0) See if newtype is a superclass of the current matrix.
4361           i.e mat is mpiaij and newtype is aij */
4362     for (i = 0; i < 2; i++) {
4363       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4365       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4366       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4367       if (flg) {
4368         if (reuse == MAT_INPLACE_MATRIX) {
4369           PetscCall(PetscInfo(mat, "Early return\n"));
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4372           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4373           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4374           PetscFunctionReturn(PETSC_SUCCESS);
4375         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4376           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4377           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4378           PetscFunctionReturn(PETSC_SUCCESS);
4379         }
4380       }
4381     }
4382     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4383     for (i = 0; i < 3; i++) {
4384       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4385       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4386       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4387       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4388       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4390       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4391       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4392       if (conv) goto foundconv;
4393     }
4394 
4395     /* 2)  See if a specialized converter is known to the desired matrix class. */
4396     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4397     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4398     PetscCall(MatSetType(B, newtype));
4399     for (i = 0; i < 3; i++) {
4400       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4401       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4402       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4403       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4404       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4405       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4406       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4407       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4408       if (conv) {
4409         PetscCall(MatDestroy(&B));
4410         goto foundconv;
4411       }
4412     }
4413 
4414     /* 3) See if a good general converter is registered for the desired class */
4415     conv = B->ops->convertfrom;
4416     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4417     PetscCall(MatDestroy(&B));
4418     if (conv) goto foundconv;
4419 
4420     /* 4) See if a good general converter is known for the current matrix */
4421     if (mat->ops->convert) conv = mat->ops->convert;
4422     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4423     if (conv) goto foundconv;
4424 
4425     /* 5) Use a really basic converter. */
4426     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4427     conv = MatConvert_Basic;
4428 
4429   foundconv:
4430     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4431     PetscCall((*conv)(mat, newtype, reuse, M));
4432     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4433       /* the block sizes must be same if the mappings are copied over */
4434       (*M)->rmap->bs = mat->rmap->bs;
4435       (*M)->cmap->bs = mat->cmap->bs;
4436       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4437       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4438       (*M)->rmap->mapping = mat->rmap->mapping;
4439       (*M)->cmap->mapping = mat->cmap->mapping;
4440     }
4441     (*M)->stencil.dim = mat->stencil.dim;
4442     (*M)->stencil.noc = mat->stencil.noc;
4443     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4444       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4445       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4446     }
4447     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4448   }
4449   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4450 
4451   /* Copy Mat options */
4452   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4453   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4454   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4455   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4456   PetscFunctionReturn(PETSC_SUCCESS);
4457 }
4458 
4459 /*@C
4460   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4461 
4462   Not Collective
4463 
4464   Input Parameter:
4465 . mat - the matrix, must be a factored matrix
4466 
4467   Output Parameter:
4468 . type - the string name of the package (do not free this string)
4469 
4470   Level: intermediate
4471 
4472   Fortran Notes:
4473   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4474 
4475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4476 @*/
4477 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4478 {
4479   PetscErrorCode (*conv)(Mat, MatSolverType *);
4480 
4481   PetscFunctionBegin;
4482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4483   PetscValidType(mat, 1);
4484   PetscAssertPointer(type, 2);
4485   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4486   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4487   if (conv) PetscCall((*conv)(mat, type));
4488   else *type = MATSOLVERPETSC;
4489   PetscFunctionReturn(PETSC_SUCCESS);
4490 }
4491 
4492 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4493 struct _MatSolverTypeForSpecifcType {
4494   MatType mtype;
4495   /* no entry for MAT_FACTOR_NONE */
4496   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4497   MatSolverTypeForSpecifcType next;
4498 };
4499 
4500 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4501 struct _MatSolverTypeHolder {
4502   char                       *name;
4503   MatSolverTypeForSpecifcType handlers;
4504   MatSolverTypeHolder         next;
4505 };
4506 
4507 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4508 
4509 /*@C
4510   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4511 
4512   Input Parameters:
4513 + package      - name of the package, for example petsc or superlu
4514 . mtype        - the matrix type that works with this package
4515 . ftype        - the type of factorization supported by the package
4516 - createfactor - routine that will create the factored matrix ready to be used
4517 
4518   Level: developer
4519 
4520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4521 @*/
4522 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4523 {
4524   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4525   PetscBool                   flg;
4526   MatSolverTypeForSpecifcType inext, iprev = NULL;
4527 
4528   PetscFunctionBegin;
4529   PetscCall(MatInitializePackage());
4530   if (!next) {
4531     PetscCall(PetscNew(&MatSolverTypeHolders));
4532     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4533     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4534     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4535     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4536     PetscFunctionReturn(PETSC_SUCCESS);
4537   }
4538   while (next) {
4539     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4540     if (flg) {
4541       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4542       inext = next->handlers;
4543       while (inext) {
4544         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4545         if (flg) {
4546           inext->createfactor[(int)ftype - 1] = createfactor;
4547           PetscFunctionReturn(PETSC_SUCCESS);
4548         }
4549         iprev = inext;
4550         inext = inext->next;
4551       }
4552       PetscCall(PetscNew(&iprev->next));
4553       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4554       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4555       PetscFunctionReturn(PETSC_SUCCESS);
4556     }
4557     prev = next;
4558     next = next->next;
4559   }
4560   PetscCall(PetscNew(&prev->next));
4561   PetscCall(PetscStrallocpy(package, &prev->next->name));
4562   PetscCall(PetscNew(&prev->next->handlers));
4563   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4564   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4565   PetscFunctionReturn(PETSC_SUCCESS);
4566 }
4567 
4568 /*@C
4569   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4570 
4571   Input Parameters:
4572 + type  - name of the package, for example petsc or superlu
4573 . ftype - the type of factorization supported by the type
4574 - mtype - the matrix type that works with this type
4575 
4576   Output Parameters:
4577 + foundtype    - `PETSC_TRUE` if the type was registered
4578 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4579 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4580 
4581   Level: developer
4582 
4583 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4584 @*/
4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4586 {
4587   MatSolverTypeHolder         next = MatSolverTypeHolders;
4588   PetscBool                   flg;
4589   MatSolverTypeForSpecifcType inext;
4590 
4591   PetscFunctionBegin;
4592   if (foundtype) *foundtype = PETSC_FALSE;
4593   if (foundmtype) *foundmtype = PETSC_FALSE;
4594   if (createfactor) *createfactor = NULL;
4595 
4596   if (type) {
4597     while (next) {
4598       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4599       if (flg) {
4600         if (foundtype) *foundtype = PETSC_TRUE;
4601         inext = next->handlers;
4602         while (inext) {
4603           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4604           if (flg) {
4605             if (foundmtype) *foundmtype = PETSC_TRUE;
4606             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4607             PetscFunctionReturn(PETSC_SUCCESS);
4608           }
4609           inext = inext->next;
4610         }
4611       }
4612       next = next->next;
4613     }
4614   } else {
4615     while (next) {
4616       inext = next->handlers;
4617       while (inext) {
4618         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4619         if (flg && inext->createfactor[(int)ftype - 1]) {
4620           if (foundtype) *foundtype = PETSC_TRUE;
4621           if (foundmtype) *foundmtype = PETSC_TRUE;
4622           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4623           PetscFunctionReturn(PETSC_SUCCESS);
4624         }
4625         inext = inext->next;
4626       }
4627       next = next->next;
4628     }
4629     /* try with base classes inext->mtype */
4630     next = MatSolverTypeHolders;
4631     while (next) {
4632       inext = next->handlers;
4633       while (inext) {
4634         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4635         if (flg && inext->createfactor[(int)ftype - 1]) {
4636           if (foundtype) *foundtype = PETSC_TRUE;
4637           if (foundmtype) *foundmtype = PETSC_TRUE;
4638           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4639           PetscFunctionReturn(PETSC_SUCCESS);
4640         }
4641         inext = inext->next;
4642       }
4643       next = next->next;
4644     }
4645   }
4646   PetscFunctionReturn(PETSC_SUCCESS);
4647 }
4648 
4649 PetscErrorCode MatSolverTypeDestroy(void)
4650 {
4651   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4652   MatSolverTypeForSpecifcType inext, iprev;
4653 
4654   PetscFunctionBegin;
4655   while (next) {
4656     PetscCall(PetscFree(next->name));
4657     inext = next->handlers;
4658     while (inext) {
4659       PetscCall(PetscFree(inext->mtype));
4660       iprev = inext;
4661       inext = inext->next;
4662       PetscCall(PetscFree(iprev));
4663     }
4664     prev = next;
4665     next = next->next;
4666     PetscCall(PetscFree(prev));
4667   }
4668   MatSolverTypeHolders = NULL;
4669   PetscFunctionReturn(PETSC_SUCCESS);
4670 }
4671 
4672 /*@C
4673   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4674 
4675   Logically Collective
4676 
4677   Input Parameter:
4678 . mat - the matrix
4679 
4680   Output Parameter:
4681 . flg - `PETSC_TRUE` if uses the ordering
4682 
4683   Level: developer
4684 
4685   Note:
4686   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4687   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4688 
4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4690 @*/
4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4692 {
4693   PetscFunctionBegin;
4694   *flg = mat->canuseordering;
4695   PetscFunctionReturn(PETSC_SUCCESS);
4696 }
4697 
4698 /*@C
4699   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4700 
4701   Logically Collective
4702 
4703   Input Parameters:
4704 + mat   - the matrix obtained with `MatGetFactor()`
4705 - ftype - the factorization type to be used
4706 
4707   Output Parameter:
4708 . otype - the preferred ordering type
4709 
4710   Level: developer
4711 
4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4713 @*/
4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4715 {
4716   PetscFunctionBegin;
4717   *otype = mat->preferredordering[ftype];
4718   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4719   PetscFunctionReturn(PETSC_SUCCESS);
4720 }
4721 
4722 /*@C
4723   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4724 
4725   Collective
4726 
4727   Input Parameters:
4728 + mat   - the matrix
4729 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4730 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4731 
4732   Output Parameter:
4733 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4734 
4735   Options Database Key:
4736 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4737                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4738 
4739   Level: intermediate
4740 
4741   Notes:
4742   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4743   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4744 
4745   Users usually access the factorization solvers via `KSP`
4746 
4747   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4748   such as pastix, superlu, mumps etc.
4749 
4750   PETSc must have been ./configure to use the external solver, using the option --download-package
4751 
4752   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4753   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4754   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4755 
4756   Developer Notes:
4757   This should actually be called `MatCreateFactor()` since it creates a new factor object
4758 
4759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4760           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4761 @*/
4762 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4763 {
4764   PetscBool foundtype, foundmtype;
4765   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4766 
4767   PetscFunctionBegin;
4768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4769   PetscValidType(mat, 1);
4770 
4771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4772   MatCheckPreallocated(mat, 1);
4773 
4774   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4775   if (!foundtype) {
4776     if (type) {
4777       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],
4778               ((PetscObject)mat)->type_name, type);
4779     } else {
4780       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);
4781     }
4782   }
4783   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4784   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);
4785 
4786   PetscCall((*conv)(mat, ftype, f));
4787   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4788   PetscFunctionReturn(PETSC_SUCCESS);
4789 }
4790 
4791 /*@C
4792   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4793 
4794   Not Collective
4795 
4796   Input Parameters:
4797 + mat   - the matrix
4798 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4800 
4801   Output Parameter:
4802 . flg - PETSC_TRUE if the factorization is available
4803 
4804   Level: intermediate
4805 
4806   Notes:
4807   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4808   such as pastix, superlu, mumps etc.
4809 
4810   PETSc must have been ./configure to use the external solver, using the option --download-package
4811 
4812   Developer Notes:
4813   This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4814 
4815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4816           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4817 @*/
4818 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4819 {
4820   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4821 
4822   PetscFunctionBegin;
4823   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4824   PetscValidType(mat, 1);
4825   PetscAssertPointer(flg, 4);
4826 
4827   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4828   MatCheckPreallocated(mat, 1);
4829 
4830   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4831   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4832   PetscFunctionReturn(PETSC_SUCCESS);
4833 }
4834 
4835 /*@
4836   MatDuplicate - Duplicates a matrix including the non-zero structure.
4837 
4838   Collective
4839 
4840   Input Parameters:
4841 + mat - the matrix
4842 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4843         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4844 
4845   Output Parameter:
4846 . M - pointer to place new matrix
4847 
4848   Level: intermediate
4849 
4850   Notes:
4851   You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4852 
4853   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.
4854 
4855   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
4856   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4857   User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4858 
4859 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4860 @*/
4861 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4862 {
4863   Mat         B;
4864   VecType     vtype;
4865   PetscInt    i;
4866   PetscObject dm, container_h, container_d;
4867   void (*viewf)(void);
4868 
4869   PetscFunctionBegin;
4870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4871   PetscValidType(mat, 1);
4872   PetscAssertPointer(M, 3);
4873   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4874   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4875   MatCheckPreallocated(mat, 1);
4876 
4877   *M = NULL;
4878   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4879   PetscUseTypeMethod(mat, duplicate, op, M);
4880   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4881   B = *M;
4882 
4883   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4884   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4885   PetscCall(MatGetVecType(mat, &vtype));
4886   PetscCall(MatSetVecType(B, vtype));
4887 
4888   B->stencil.dim = mat->stencil.dim;
4889   B->stencil.noc = mat->stencil.noc;
4890   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4891     B->stencil.dims[i]   = mat->stencil.dims[i];
4892     B->stencil.starts[i] = mat->stencil.starts[i];
4893   }
4894 
4895   B->nooffproczerorows = mat->nooffproczerorows;
4896   B->nooffprocentries  = mat->nooffprocentries;
4897 
4898   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4899   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4900   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4901   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4902   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4903   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4904   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4905   PetscFunctionReturn(PETSC_SUCCESS);
4906 }
4907 
4908 /*@
4909   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4910 
4911   Logically Collective
4912 
4913   Input Parameter:
4914 . mat - the matrix
4915 
4916   Output Parameter:
4917 . v - the diagonal of the matrix
4918 
4919   Level: intermediate
4920 
4921   Note:
4922   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4923   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4924   is larger than `ndiag`, the values of the remaining entries are unspecified.
4925 
4926   Currently only correct in parallel for square matrices.
4927 
4928 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4929 @*/
4930 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4931 {
4932   PetscFunctionBegin;
4933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4934   PetscValidType(mat, 1);
4935   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4936   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4937   MatCheckPreallocated(mat, 1);
4938   if (PetscDefined(USE_DEBUG)) {
4939     PetscInt nv, row, col, ndiag;
4940 
4941     PetscCall(VecGetLocalSize(v, &nv));
4942     PetscCall(MatGetLocalSize(mat, &row, &col));
4943     ndiag = PetscMin(row, col);
4944     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);
4945   }
4946 
4947   PetscUseTypeMethod(mat, getdiagonal, v);
4948   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4949   PetscFunctionReturn(PETSC_SUCCESS);
4950 }
4951 
4952 /*@C
4953   MatGetRowMin - Gets the minimum value (of the real part) of each
4954   row of the matrix
4955 
4956   Logically Collective
4957 
4958   Input Parameter:
4959 . mat - the matrix
4960 
4961   Output Parameters:
4962 + v   - the vector for storing the maximums
4963 - idx - the indices of the column found for each row (optional)
4964 
4965   Level: intermediate
4966 
4967   Note:
4968   The result of this call are the same as if one converted the matrix to dense format
4969   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4970 
4971   This code is only implemented for a couple of matrix formats.
4972 
4973 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4974           `MatGetRowMax()`
4975 @*/
4976 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4977 {
4978   PetscFunctionBegin;
4979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4980   PetscValidType(mat, 1);
4981   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4982   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4983 
4984   if (!mat->cmap->N) {
4985     PetscCall(VecSet(v, PETSC_MAX_REAL));
4986     if (idx) {
4987       PetscInt i, m = mat->rmap->n;
4988       for (i = 0; i < m; i++) idx[i] = -1;
4989     }
4990   } else {
4991     MatCheckPreallocated(mat, 1);
4992   }
4993   PetscUseTypeMethod(mat, getrowmin, v, idx);
4994   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4995   PetscFunctionReturn(PETSC_SUCCESS);
4996 }
4997 
4998 /*@C
4999   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5000   row of the matrix
5001 
5002   Logically Collective
5003 
5004   Input Parameter:
5005 . mat - the matrix
5006 
5007   Output Parameters:
5008 + v   - the vector for storing the minimums
5009 - idx - the indices of the column found for each row (or `NULL` if not needed)
5010 
5011   Level: intermediate
5012 
5013   Notes:
5014   if a row is completely empty or has only 0.0 values then the idx[] value for that
5015   row is 0 (the first column).
5016 
5017   This code is only implemented for a couple of matrix formats.
5018 
5019 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5020 @*/
5021 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5022 {
5023   PetscFunctionBegin;
5024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5025   PetscValidType(mat, 1);
5026   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5027   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5028   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5029 
5030   if (!mat->cmap->N) {
5031     PetscCall(VecSet(v, 0.0));
5032     if (idx) {
5033       PetscInt i, m = mat->rmap->n;
5034       for (i = 0; i < m; i++) idx[i] = -1;
5035     }
5036   } else {
5037     MatCheckPreallocated(mat, 1);
5038     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5039     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5040   }
5041   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5042   PetscFunctionReturn(PETSC_SUCCESS);
5043 }
5044 
5045 /*@C
5046   MatGetRowMax - Gets the maximum value (of the real part) of each
5047   row of the matrix
5048 
5049   Logically Collective
5050 
5051   Input Parameter:
5052 . mat - the matrix
5053 
5054   Output Parameters:
5055 + v   - the vector for storing the maximums
5056 - idx - the indices of the column found for each row (optional)
5057 
5058   Level: intermediate
5059 
5060   Notes:
5061   The result of this call are the same as if one converted the matrix to dense format
5062   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5063 
5064   This code is only implemented for a couple of matrix formats.
5065 
5066 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5067 @*/
5068 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5069 {
5070   PetscFunctionBegin;
5071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5072   PetscValidType(mat, 1);
5073   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5074   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5075 
5076   if (!mat->cmap->N) {
5077     PetscCall(VecSet(v, PETSC_MIN_REAL));
5078     if (idx) {
5079       PetscInt i, m = mat->rmap->n;
5080       for (i = 0; i < m; i++) idx[i] = -1;
5081     }
5082   } else {
5083     MatCheckPreallocated(mat, 1);
5084     PetscUseTypeMethod(mat, getrowmax, v, idx);
5085   }
5086   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5087   PetscFunctionReturn(PETSC_SUCCESS);
5088 }
5089 
5090 /*@C
5091   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5092   row of the matrix
5093 
5094   Logically Collective
5095 
5096   Input Parameter:
5097 . mat - the matrix
5098 
5099   Output Parameters:
5100 + v   - the vector for storing the maximums
5101 - idx - the indices of the column found for each row (or `NULL` if not needed)
5102 
5103   Level: intermediate
5104 
5105   Notes:
5106   if a row is completely empty or has only 0.0 values then the idx[] value for that
5107   row is 0 (the first column).
5108 
5109   This code is only implemented for a couple of matrix formats.
5110 
5111 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5112 @*/
5113 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5114 {
5115   PetscFunctionBegin;
5116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5117   PetscValidType(mat, 1);
5118   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5119   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5120 
5121   if (!mat->cmap->N) {
5122     PetscCall(VecSet(v, 0.0));
5123     if (idx) {
5124       PetscInt i, m = mat->rmap->n;
5125       for (i = 0; i < m; i++) idx[i] = -1;
5126     }
5127   } else {
5128     MatCheckPreallocated(mat, 1);
5129     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5130     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5131   }
5132   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5133   PetscFunctionReturn(PETSC_SUCCESS);
5134 }
5135 
5136 /*@
5137   MatGetRowSum - Gets the sum of each row of the matrix
5138 
5139   Logically or Neighborhood Collective
5140 
5141   Input Parameter:
5142 . mat - the matrix
5143 
5144   Output Parameter:
5145 . v - the vector for storing the sum of rows
5146 
5147   Level: intermediate
5148 
5149   Notes:
5150   This code is slow since it is not currently specialized for different formats
5151 
5152 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5153 @*/
5154 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5155 {
5156   Vec ones;
5157 
5158   PetscFunctionBegin;
5159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5160   PetscValidType(mat, 1);
5161   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5162   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5163   MatCheckPreallocated(mat, 1);
5164   PetscCall(MatCreateVecs(mat, &ones, NULL));
5165   PetscCall(VecSet(ones, 1.));
5166   PetscCall(MatMult(mat, ones, v));
5167   PetscCall(VecDestroy(&ones));
5168   PetscFunctionReturn(PETSC_SUCCESS);
5169 }
5170 
5171 /*@
5172   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5173   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5174 
5175   Collective
5176 
5177   Input Parameter:
5178 . mat - the matrix to provide the transpose
5179 
5180   Output Parameter:
5181 . 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
5182 
5183   Level: advanced
5184 
5185   Note:
5186   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
5187   routine allows bypassing that call.
5188 
5189 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5190 @*/
5191 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5192 {
5193   PetscContainer  rB = NULL;
5194   MatParentState *rb = NULL;
5195 
5196   PetscFunctionBegin;
5197   PetscCall(PetscNew(&rb));
5198   rb->id    = ((PetscObject)mat)->id;
5199   rb->state = 0;
5200   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5201   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5202   PetscCall(PetscContainerSetPointer(rB, rb));
5203   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5204   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5205   PetscCall(PetscObjectDereference((PetscObject)rB));
5206   PetscFunctionReturn(PETSC_SUCCESS);
5207 }
5208 
5209 /*@
5210   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5211 
5212   Collective
5213 
5214   Input Parameters:
5215 + mat   - the matrix to transpose
5216 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5217 
5218   Output Parameter:
5219 . B - the transpose
5220 
5221   Level: intermediate
5222 
5223   Notes:
5224   If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5225 
5226   `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
5227   transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5228 
5229   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.
5230 
5231   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5232 
5233   If mat is unchanged from the last call this function returns immediately without recomputing the result
5234 
5235   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5236 
5237 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5238           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5239 @*/
5240 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5241 {
5242   PetscContainer  rB = NULL;
5243   MatParentState *rb = NULL;
5244 
5245   PetscFunctionBegin;
5246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5247   PetscValidType(mat, 1);
5248   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5249   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5250   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5251   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5252   MatCheckPreallocated(mat, 1);
5253   if (reuse == MAT_REUSE_MATRIX) {
5254     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5255     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5256     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5257     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5258     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5259   }
5260 
5261   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5262   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5263     PetscUseTypeMethod(mat, transpose, reuse, B);
5264     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5265   }
5266   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5267 
5268   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5269   if (reuse != MAT_INPLACE_MATRIX) {
5270     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5271     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5272     rb->state        = ((PetscObject)mat)->state;
5273     rb->nonzerostate = mat->nonzerostate;
5274   }
5275   PetscFunctionReturn(PETSC_SUCCESS);
5276 }
5277 
5278 /*@
5279   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5280 
5281   Collective
5282 
5283   Input Parameter:
5284 . A - the matrix to transpose
5285 
5286   Output Parameter:
5287 . 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
5288       numerical portion.
5289 
5290   Level: intermediate
5291 
5292   Note:
5293   This is not supported for many matrix types, use `MatTranspose()` in those cases
5294 
5295 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5296 @*/
5297 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5298 {
5299   PetscFunctionBegin;
5300   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5301   PetscValidType(A, 1);
5302   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5303   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5304   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5305   PetscUseTypeMethod(A, transposesymbolic, B);
5306   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5307 
5308   PetscCall(MatTransposeSetPrecursor(A, *B));
5309   PetscFunctionReturn(PETSC_SUCCESS);
5310 }
5311 
5312 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5313 {
5314   PetscContainer  rB;
5315   MatParentState *rb;
5316 
5317   PetscFunctionBegin;
5318   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5319   PetscValidType(A, 1);
5320   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5321   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5322   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5323   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5324   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5325   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5326   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5327   PetscFunctionReturn(PETSC_SUCCESS);
5328 }
5329 
5330 /*@
5331   MatIsTranspose - Test whether a matrix is another one's transpose,
5332   or its own, in which case it tests symmetry.
5333 
5334   Collective
5335 
5336   Input Parameters:
5337 + A   - the matrix to test
5338 . B   - the matrix to test against, this can equal the first parameter
5339 - tol - tolerance, differences between entries smaller than this are counted as zero
5340 
5341   Output Parameter:
5342 . flg - the result
5343 
5344   Level: intermediate
5345 
5346   Notes:
5347   Only available for `MATAIJ` matrices.
5348 
5349   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5350   test involves parallel copies of the block off-diagonal parts of the matrix.
5351 
5352 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5353 @*/
5354 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5355 {
5356   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5357 
5358   PetscFunctionBegin;
5359   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5360   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5361   PetscAssertPointer(flg, 4);
5362   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5363   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5364   *flg = PETSC_FALSE;
5365   if (f && g) {
5366     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5367     PetscCall((*f)(A, B, tol, flg));
5368   } else {
5369     MatType mattype;
5370 
5371     PetscCall(MatGetType(f ? B : A, &mattype));
5372     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5373   }
5374   PetscFunctionReturn(PETSC_SUCCESS);
5375 }
5376 
5377 /*@
5378   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5379 
5380   Collective
5381 
5382   Input Parameters:
5383 + mat   - the matrix to transpose and complex conjugate
5384 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5385 
5386   Output Parameter:
5387 . B - the Hermitian transpose
5388 
5389   Level: intermediate
5390 
5391 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5392 @*/
5393 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5394 {
5395   PetscFunctionBegin;
5396   PetscCall(MatTranspose(mat, reuse, B));
5397 #if defined(PETSC_USE_COMPLEX)
5398   PetscCall(MatConjugate(*B));
5399 #endif
5400   PetscFunctionReturn(PETSC_SUCCESS);
5401 }
5402 
5403 /*@
5404   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5405 
5406   Collective
5407 
5408   Input Parameters:
5409 + A   - the matrix to test
5410 . B   - the matrix to test against, this can equal the first parameter
5411 - tol - tolerance, differences between entries smaller than this are counted as zero
5412 
5413   Output Parameter:
5414 . flg - the result
5415 
5416   Level: intermediate
5417 
5418   Notes:
5419   Only available for `MATAIJ` matrices.
5420 
5421   The sequential algorithm
5422   has a running time of the order of the number of nonzeros; the parallel
5423   test involves parallel copies of the block off-diagonal parts of the matrix.
5424 
5425 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5426 @*/
5427 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5428 {
5429   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5430 
5431   PetscFunctionBegin;
5432   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5433   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5434   PetscAssertPointer(flg, 4);
5435   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5436   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5437   if (f && g) {
5438     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5439     PetscCall((*f)(A, B, tol, flg));
5440   }
5441   PetscFunctionReturn(PETSC_SUCCESS);
5442 }
5443 
5444 /*@
5445   MatPermute - Creates a new matrix with rows and columns permuted from the
5446   original.
5447 
5448   Collective
5449 
5450   Input Parameters:
5451 + mat - the matrix to permute
5452 . row - row permutation, each processor supplies only the permutation for its rows
5453 - col - column permutation, each processor supplies only the permutation for its columns
5454 
5455   Output Parameter:
5456 . B - the permuted matrix
5457 
5458   Level: advanced
5459 
5460   Note:
5461   The index sets map from row/col of permuted matrix to row/col of original matrix.
5462   The index sets should be on the same communicator as mat and have the same local sizes.
5463 
5464   Developer Notes:
5465   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5466   exploit the fact that row and col are permutations, consider implementing the
5467   more general `MatCreateSubMatrix()` instead.
5468 
5469 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5470 @*/
5471 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5472 {
5473   PetscFunctionBegin;
5474   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5475   PetscValidType(mat, 1);
5476   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5477   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5478   PetscAssertPointer(B, 4);
5479   PetscCheckSameComm(mat, 1, row, 2);
5480   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5481   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5482   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5483   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5484   MatCheckPreallocated(mat, 1);
5485 
5486   if (mat->ops->permute) {
5487     PetscUseTypeMethod(mat, permute, row, col, B);
5488     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5489   } else {
5490     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5491   }
5492   PetscFunctionReturn(PETSC_SUCCESS);
5493 }
5494 
5495 /*@
5496   MatEqual - Compares two matrices.
5497 
5498   Collective
5499 
5500   Input Parameters:
5501 + A - the first matrix
5502 - B - the second matrix
5503 
5504   Output Parameter:
5505 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5506 
5507   Level: intermediate
5508 
5509 .seealso: [](ch_matrices), `Mat`
5510 @*/
5511 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5512 {
5513   PetscFunctionBegin;
5514   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5515   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5516   PetscValidType(A, 1);
5517   PetscValidType(B, 2);
5518   PetscAssertPointer(flg, 3);
5519   PetscCheckSameComm(A, 1, B, 2);
5520   MatCheckPreallocated(A, 1);
5521   MatCheckPreallocated(B, 2);
5522   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5523   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5524   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,
5525              B->cmap->N);
5526   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5527     PetscUseTypeMethod(A, equal, B, flg);
5528   } else {
5529     PetscCall(MatMultEqual(A, B, 10, flg));
5530   }
5531   PetscFunctionReturn(PETSC_SUCCESS);
5532 }
5533 
5534 /*@
5535   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5536   matrices that are stored as vectors.  Either of the two scaling
5537   matrices can be `NULL`.
5538 
5539   Collective
5540 
5541   Input Parameters:
5542 + mat - the matrix to be scaled
5543 . l   - the left scaling vector (or `NULL`)
5544 - r   - the right scaling vector (or `NULL`)
5545 
5546   Level: intermediate
5547 
5548   Note:
5549   `MatDiagonalScale()` computes A = LAR, where
5550   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5551   The L scales the rows of the matrix, the R scales the columns of the matrix.
5552 
5553 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5554 @*/
5555 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5556 {
5557   PetscFunctionBegin;
5558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5559   PetscValidType(mat, 1);
5560   if (l) {
5561     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5562     PetscCheckSameComm(mat, 1, l, 2);
5563   }
5564   if (r) {
5565     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5566     PetscCheckSameComm(mat, 1, r, 3);
5567   }
5568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5570   MatCheckPreallocated(mat, 1);
5571   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5572 
5573   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5574   PetscUseTypeMethod(mat, diagonalscale, l, r);
5575   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5576   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5577   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5578   PetscFunctionReturn(PETSC_SUCCESS);
5579 }
5580 
5581 /*@
5582   MatScale - Scales all elements of a matrix by a given number.
5583 
5584   Logically Collective
5585 
5586   Input Parameters:
5587 + mat - the matrix to be scaled
5588 - a   - the scaling value
5589 
5590   Level: intermediate
5591 
5592 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5593 @*/
5594 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5595 {
5596   PetscFunctionBegin;
5597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5598   PetscValidType(mat, 1);
5599   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5600   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5601   PetscValidLogicalCollectiveScalar(mat, a, 2);
5602   MatCheckPreallocated(mat, 1);
5603 
5604   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5605   if (a != (PetscScalar)1.0) {
5606     PetscUseTypeMethod(mat, scale, a);
5607     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5608   }
5609   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5610   PetscFunctionReturn(PETSC_SUCCESS);
5611 }
5612 
5613 /*@
5614   MatNorm - Calculates various norms of a matrix.
5615 
5616   Collective
5617 
5618   Input Parameters:
5619 + mat  - the matrix
5620 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5621 
5622   Output Parameter:
5623 . nrm - the resulting norm
5624 
5625   Level: intermediate
5626 
5627 .seealso: [](ch_matrices), `Mat`
5628 @*/
5629 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5630 {
5631   PetscFunctionBegin;
5632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5633   PetscValidType(mat, 1);
5634   PetscAssertPointer(nrm, 3);
5635 
5636   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5637   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5638   MatCheckPreallocated(mat, 1);
5639 
5640   PetscUseTypeMethod(mat, norm, type, nrm);
5641   PetscFunctionReturn(PETSC_SUCCESS);
5642 }
5643 
5644 /*
5645      This variable is used to prevent counting of MatAssemblyBegin() that
5646    are called from within a MatAssemblyEnd().
5647 */
5648 static PetscInt MatAssemblyEnd_InUse = 0;
5649 /*@
5650   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5651   be called after completing all calls to `MatSetValues()`.
5652 
5653   Collective
5654 
5655   Input Parameters:
5656 + mat  - the matrix
5657 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5658 
5659   Level: beginner
5660 
5661   Notes:
5662   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5663   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5664 
5665   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5666   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5667   using the matrix.
5668 
5669   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5670   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
5671   a global collective operation requiring all processes that share the matrix.
5672 
5673   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5674   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5675   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5676 
5677 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5678 @*/
5679 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5680 {
5681   PetscFunctionBegin;
5682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5683   PetscValidType(mat, 1);
5684   MatCheckPreallocated(mat, 1);
5685   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5686   if (mat->assembled) {
5687     mat->was_assembled = PETSC_TRUE;
5688     mat->assembled     = PETSC_FALSE;
5689   }
5690 
5691   if (!MatAssemblyEnd_InUse) {
5692     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5693     PetscTryTypeMethod(mat, assemblybegin, type);
5694     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5695   } else PetscTryTypeMethod(mat, assemblybegin, type);
5696   PetscFunctionReturn(PETSC_SUCCESS);
5697 }
5698 
5699 /*@
5700   MatAssembled - Indicates if a matrix has been assembled and is ready for
5701   use; for example, in matrix-vector product.
5702 
5703   Not Collective
5704 
5705   Input Parameter:
5706 . mat - the matrix
5707 
5708   Output Parameter:
5709 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5710 
5711   Level: advanced
5712 
5713 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5714 @*/
5715 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5716 {
5717   PetscFunctionBegin;
5718   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5719   PetscAssertPointer(assembled, 2);
5720   *assembled = mat->assembled;
5721   PetscFunctionReturn(PETSC_SUCCESS);
5722 }
5723 
5724 /*@
5725   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5726   be called after `MatAssemblyBegin()`.
5727 
5728   Collective
5729 
5730   Input Parameters:
5731 + mat  - the matrix
5732 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5733 
5734   Options Database Keys:
5735 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5736 . -mat_view ::ascii_info_detail      - Prints more detailed info
5737 . -mat_view                          - Prints matrix in ASCII format
5738 . -mat_view ::ascii_matlab           - Prints matrix in Matlab format
5739 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5740 . -display <name>                    - Sets display name (default is host)
5741 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5742 . -mat_view socket                   - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5743 . -viewer_socket_machine <machine>   - Machine to use for socket
5744 . -viewer_socket_port <port>         - Port number to use for socket
5745 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5746 
5747   Level: beginner
5748 
5749 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5750 @*/
5751 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5752 {
5753   static PetscInt inassm = 0;
5754   PetscBool       flg    = PETSC_FALSE;
5755 
5756   PetscFunctionBegin;
5757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5758   PetscValidType(mat, 1);
5759 
5760   inassm++;
5761   MatAssemblyEnd_InUse++;
5762   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5763     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5764     PetscTryTypeMethod(mat, assemblyend, type);
5765     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5766   } else PetscTryTypeMethod(mat, assemblyend, type);
5767 
5768   /* Flush assembly is not a true assembly */
5769   if (type != MAT_FLUSH_ASSEMBLY) {
5770     if (mat->num_ass) {
5771       if (!mat->symmetry_eternal) {
5772         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5773         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5774       }
5775       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5776       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5777     }
5778     mat->num_ass++;
5779     mat->assembled        = PETSC_TRUE;
5780     mat->ass_nonzerostate = mat->nonzerostate;
5781   }
5782 
5783   mat->insertmode = NOT_SET_VALUES;
5784   MatAssemblyEnd_InUse--;
5785   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5786   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5787     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5788 
5789     if (mat->checksymmetryonassembly) {
5790       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5791       if (flg) {
5792         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5793       } else {
5794         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5795       }
5796     }
5797     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5798   }
5799   inassm--;
5800   PetscFunctionReturn(PETSC_SUCCESS);
5801 }
5802 
5803 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5804 /*@
5805   MatSetOption - Sets a parameter option for a matrix. Some options
5806   may be specific to certain storage formats.  Some options
5807   determine how values will be inserted (or added). Sorted,
5808   row-oriented input will generally assemble the fastest. The default
5809   is row-oriented.
5810 
5811   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5812 
5813   Input Parameters:
5814 + mat - the matrix
5815 . op  - the option, one of those listed below (and possibly others),
5816 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5817 
5818   Options Describing Matrix Structure:
5819 + `MAT_SPD`                         - symmetric positive definite
5820 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5821 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5822 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5823 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5824 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5825 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5826 
5827    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5828    do not need to be computed (usually at a high cost)
5829 
5830    Options For Use with `MatSetValues()`:
5831    Insert a logically dense subblock, which can be
5832 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5833 
5834    These options reflect the data you pass in with `MatSetValues()`; it has
5835    nothing to do with how the data is stored internally in the matrix
5836    data structure.
5837 
5838    When (re)assembling a matrix, we can restrict the input for
5839    efficiency/debugging purposes.  These options include
5840 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5841 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5842 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5843 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5844 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5845 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5846         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5847         performance for very large process counts.
5848 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5849         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5850         functions, instead sending only neighbor messages.
5851 
5852   Level: intermediate
5853 
5854   Notes:
5855   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5856 
5857   Some options are relevant only for particular matrix types and
5858   are thus ignored by others.  Other options are not supported by
5859   certain matrix types and will generate an error message if set.
5860 
5861   If using Fortran to compute a matrix, one may need to
5862   use the column-oriented option (or convert to the row-oriented
5863   format).
5864 
5865   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5866   that would generate a new entry in the nonzero structure is instead
5867   ignored.  Thus, if memory has not already been allocated for this particular
5868   data, then the insertion is ignored. For dense matrices, in which
5869   the entire array is allocated, no entries are ever ignored.
5870   Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5871 
5872   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5873   that would generate a new entry in the nonzero structure instead produces
5874   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
5875 
5876   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5877   that would generate a new entry that has not been preallocated will
5878   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5879   only.) This is a useful flag when debugging matrix memory preallocation.
5880   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5881 
5882   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5883   other processors should be dropped, rather than stashed.
5884   This is useful if you know that the "owning" processor is also
5885   always generating the correct matrix entries, so that PETSc need
5886   not transfer duplicate entries generated on another processor.
5887 
5888   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5889   searches during matrix assembly. When this flag is set, the hash table
5890   is created during the first matrix assembly. This hash table is
5891   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5892   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5893   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5894   supported by `MATMPIBAIJ` format only.
5895 
5896   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5897   are kept in the nonzero structure
5898 
5899   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5900   a zero location in the matrix
5901 
5902   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5903 
5904   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5905   zero row routines and thus improves performance for very large process counts.
5906 
5907   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5908   part of the matrix (since they should match the upper triangular part).
5909 
5910   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5911   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5912   with finite difference schemes with non-periodic boundary conditions.
5913 
5914   Developer Notes:
5915   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5916   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5917   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5918   not changed.
5919 
5920 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5921 @*/
5922 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5923 {
5924   PetscFunctionBegin;
5925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5926   if (op > 0) {
5927     PetscValidLogicalCollectiveEnum(mat, op, 2);
5928     PetscValidLogicalCollectiveBool(mat, flg, 3);
5929   }
5930 
5931   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);
5932 
5933   switch (op) {
5934   case MAT_FORCE_DIAGONAL_ENTRIES:
5935     mat->force_diagonals = flg;
5936     PetscFunctionReturn(PETSC_SUCCESS);
5937   case MAT_NO_OFF_PROC_ENTRIES:
5938     mat->nooffprocentries = flg;
5939     PetscFunctionReturn(PETSC_SUCCESS);
5940   case MAT_SUBSET_OFF_PROC_ENTRIES:
5941     mat->assembly_subset = flg;
5942     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5943 #if !defined(PETSC_HAVE_MPIUNI)
5944       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5945 #endif
5946       mat->stash.first_assembly_done = PETSC_FALSE;
5947     }
5948     PetscFunctionReturn(PETSC_SUCCESS);
5949   case MAT_NO_OFF_PROC_ZERO_ROWS:
5950     mat->nooffproczerorows = flg;
5951     PetscFunctionReturn(PETSC_SUCCESS);
5952   case MAT_SPD:
5953     if (flg) {
5954       mat->spd                    = PETSC_BOOL3_TRUE;
5955       mat->symmetric              = PETSC_BOOL3_TRUE;
5956       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5957     } else {
5958       mat->spd = PETSC_BOOL3_FALSE;
5959     }
5960     break;
5961   case MAT_SYMMETRIC:
5962     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5963     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5964 #if !defined(PETSC_USE_COMPLEX)
5965     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5966 #endif
5967     break;
5968   case MAT_HERMITIAN:
5969     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5970     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5971 #if !defined(PETSC_USE_COMPLEX)
5972     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5973 #endif
5974     break;
5975   case MAT_STRUCTURALLY_SYMMETRIC:
5976     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5977     break;
5978   case MAT_SYMMETRY_ETERNAL:
5979     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");
5980     mat->symmetry_eternal = flg;
5981     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5982     break;
5983   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5984     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false");
5985     mat->structural_symmetry_eternal = flg;
5986     break;
5987   case MAT_SPD_ETERNAL:
5988     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");
5989     mat->spd_eternal = flg;
5990     if (flg) {
5991       mat->structural_symmetry_eternal = PETSC_TRUE;
5992       mat->symmetry_eternal            = PETSC_TRUE;
5993     }
5994     break;
5995   case MAT_STRUCTURE_ONLY:
5996     mat->structure_only = flg;
5997     break;
5998   case MAT_SORTED_FULL:
5999     mat->sortedfull = flg;
6000     break;
6001   default:
6002     break;
6003   }
6004   PetscTryTypeMethod(mat, setoption, op, flg);
6005   PetscFunctionReturn(PETSC_SUCCESS);
6006 }
6007 
6008 /*@
6009   MatGetOption - Gets a parameter option that has been set for a matrix.
6010 
6011   Logically Collective
6012 
6013   Input Parameters:
6014 + mat - the matrix
6015 - op  - the option, this only responds to certain options, check the code for which ones
6016 
6017   Output Parameter:
6018 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6019 
6020   Level: intermediate
6021 
6022   Notes:
6023   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6024 
6025   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6026   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6027 
6028 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6029     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6030 @*/
6031 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6032 {
6033   PetscFunctionBegin;
6034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6035   PetscValidType(mat, 1);
6036 
6037   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);
6038   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()");
6039 
6040   switch (op) {
6041   case MAT_NO_OFF_PROC_ENTRIES:
6042     *flg = mat->nooffprocentries;
6043     break;
6044   case MAT_NO_OFF_PROC_ZERO_ROWS:
6045     *flg = mat->nooffproczerorows;
6046     break;
6047   case MAT_SYMMETRIC:
6048     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6049     break;
6050   case MAT_HERMITIAN:
6051     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6052     break;
6053   case MAT_STRUCTURALLY_SYMMETRIC:
6054     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6055     break;
6056   case MAT_SPD:
6057     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6058     break;
6059   case MAT_SYMMETRY_ETERNAL:
6060     *flg = mat->symmetry_eternal;
6061     break;
6062   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6063     *flg = mat->symmetry_eternal;
6064     break;
6065   default:
6066     break;
6067   }
6068   PetscFunctionReturn(PETSC_SUCCESS);
6069 }
6070 
6071 /*@
6072   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6073   this routine retains the old nonzero structure.
6074 
6075   Logically Collective
6076 
6077   Input Parameter:
6078 . mat - the matrix
6079 
6080   Level: intermediate
6081 
6082   Note:
6083   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.
6084   See the Performance chapter of the users manual for information on preallocating matrices.
6085 
6086 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6087 @*/
6088 PetscErrorCode MatZeroEntries(Mat mat)
6089 {
6090   PetscFunctionBegin;
6091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6092   PetscValidType(mat, 1);
6093   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6094   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");
6095   MatCheckPreallocated(mat, 1);
6096 
6097   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6098   PetscUseTypeMethod(mat, zeroentries);
6099   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6100   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6101   PetscFunctionReturn(PETSC_SUCCESS);
6102 }
6103 
6104 /*@
6105   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6106   of a set of rows and columns of a matrix.
6107 
6108   Collective
6109 
6110   Input Parameters:
6111 + mat     - the matrix
6112 . numRows - the number of rows/columns to zero
6113 . rows    - the global row indices
6114 . diag    - value put in the diagonal of the eliminated rows
6115 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6116 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6117 
6118   Level: intermediate
6119 
6120   Notes:
6121   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6122 
6123   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6124   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
6125 
6126   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6127   Krylov method to take advantage of the known solution on the zeroed rows.
6128 
6129   For the parallel case, all processes that share the matrix (i.e.,
6130   those in the communicator used for matrix creation) MUST call this
6131   routine, regardless of whether any rows being zeroed are owned by
6132   them.
6133 
6134   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6135 
6136   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6137   list only rows local to itself).
6138 
6139   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6140 
6141 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6142           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6143 @*/
6144 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6145 {
6146   PetscFunctionBegin;
6147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6148   PetscValidType(mat, 1);
6149   if (numRows) PetscAssertPointer(rows, 3);
6150   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6151   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6152   MatCheckPreallocated(mat, 1);
6153 
6154   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6155   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6156   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6157   PetscFunctionReturn(PETSC_SUCCESS);
6158 }
6159 
6160 /*@
6161   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6162   of a set of rows and columns of a matrix.
6163 
6164   Collective
6165 
6166   Input Parameters:
6167 + mat  - the matrix
6168 . is   - the rows to zero
6169 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6170 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6171 - b    - optional vector of right hand side, that will be adjusted by provided solution
6172 
6173   Level: intermediate
6174 
6175   Note:
6176   See `MatZeroRowsColumns()` for details on how this routine operates.
6177 
6178 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6179           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6180 @*/
6181 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6182 {
6183   PetscInt        numRows;
6184   const PetscInt *rows;
6185 
6186   PetscFunctionBegin;
6187   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6188   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6189   PetscValidType(mat, 1);
6190   PetscValidType(is, 2);
6191   PetscCall(ISGetLocalSize(is, &numRows));
6192   PetscCall(ISGetIndices(is, &rows));
6193   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6194   PetscCall(ISRestoreIndices(is, &rows));
6195   PetscFunctionReturn(PETSC_SUCCESS);
6196 }
6197 
6198 /*@
6199   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6200   of a set of rows of a matrix.
6201 
6202   Collective
6203 
6204   Input Parameters:
6205 + mat     - the matrix
6206 . numRows - the number of rows to zero
6207 . rows    - the global row indices
6208 . diag    - value put in the diagonal of the zeroed rows
6209 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6210 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6211 
6212   Level: intermediate
6213 
6214   Notes:
6215   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6216 
6217   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6218 
6219   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6220   Krylov method to take advantage of the known solution on the zeroed rows.
6221 
6222   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)
6223   from the matrix.
6224 
6225   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6226   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
6227   formats this does not alter the nonzero structure.
6228 
6229   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6230   of the matrix is not changed the values are
6231   merely zeroed.
6232 
6233   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6234   formats can optionally remove the main diagonal entry from the
6235   nonzero structure as well, by passing 0.0 as the final argument).
6236 
6237   For the parallel case, all processes that share the matrix (i.e.,
6238   those in the communicator used for matrix creation) MUST call this
6239   routine, regardless of whether any rows being zeroed are owned by
6240   them.
6241 
6242   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6243   list only rows local to itself).
6244 
6245   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6246   owns that are to be zeroed. This saves a global synchronization in the implementation.
6247 
6248 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6249           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6250 @*/
6251 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6252 {
6253   PetscFunctionBegin;
6254   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6255   PetscValidType(mat, 1);
6256   if (numRows) PetscAssertPointer(rows, 3);
6257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6259   MatCheckPreallocated(mat, 1);
6260 
6261   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6262   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6263   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6264   PetscFunctionReturn(PETSC_SUCCESS);
6265 }
6266 
6267 /*@
6268   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6269   of a set of rows of a matrix.
6270 
6271   Collective
6272 
6273   Input Parameters:
6274 + mat  - the matrix
6275 . is   - index set of rows to remove (if `NULL` then no row is removed)
6276 . diag - value put in all diagonals of eliminated rows
6277 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6278 - b    - optional vector of right hand side, that will be adjusted by provided solution
6279 
6280   Level: intermediate
6281 
6282   Note:
6283   See `MatZeroRows()` for details on how this routine operates.
6284 
6285 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6286           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6287 @*/
6288 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6289 {
6290   PetscInt        numRows = 0;
6291   const PetscInt *rows    = NULL;
6292 
6293   PetscFunctionBegin;
6294   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6295   PetscValidType(mat, 1);
6296   if (is) {
6297     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6298     PetscCall(ISGetLocalSize(is, &numRows));
6299     PetscCall(ISGetIndices(is, &rows));
6300   }
6301   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6302   if (is) PetscCall(ISRestoreIndices(is, &rows));
6303   PetscFunctionReturn(PETSC_SUCCESS);
6304 }
6305 
6306 /*@
6307   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6308   of a set of rows of a matrix. These rows must be local to the process.
6309 
6310   Collective
6311 
6312   Input Parameters:
6313 + mat     - the matrix
6314 . numRows - the number of rows to remove
6315 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6316 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6317 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6318 - b       - optional vector of right hand side, that will be adjusted by provided solution
6319 
6320   Level: intermediate
6321 
6322   Notes:
6323   See `MatZeroRows()` for details on how this routine operates.
6324 
6325   The grid coordinates are across the entire grid, not just the local portion
6326 
6327   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6328   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6329   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6330   `DM_BOUNDARY_PERIODIC` boundary type.
6331 
6332   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
6333   a single value per point) you can skip filling those indices.
6334 
6335   Fortran Notes:
6336   `idxm` and `idxn` should be declared as
6337 $     MatStencil idxm(4, m)
6338   and the values inserted using
6339 .vb
6340     idxm(MatStencil_i, 1) = i
6341     idxm(MatStencil_j, 1) = j
6342     idxm(MatStencil_k, 1) = k
6343     idxm(MatStencil_c, 1) = c
6344    etc
6345 .ve
6346 
6347 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6348           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6349 @*/
6350 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6351 {
6352   PetscInt  dim    = mat->stencil.dim;
6353   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6354   PetscInt *dims   = mat->stencil.dims + 1;
6355   PetscInt *starts = mat->stencil.starts;
6356   PetscInt *dxm    = (PetscInt *)rows;
6357   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6358 
6359   PetscFunctionBegin;
6360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6361   PetscValidType(mat, 1);
6362   if (numRows) PetscAssertPointer(rows, 3);
6363 
6364   PetscCall(PetscMalloc1(numRows, &jdxm));
6365   for (i = 0; i < numRows; ++i) {
6366     /* Skip unused dimensions (they are ordered k, j, i, c) */
6367     for (j = 0; j < 3 - sdim; ++j) dxm++;
6368     /* Local index in X dir */
6369     tmp = *dxm++ - starts[0];
6370     /* Loop over remaining dimensions */
6371     for (j = 0; j < dim - 1; ++j) {
6372       /* If nonlocal, set index to be negative */
6373       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6374       /* Update local index */
6375       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6376     }
6377     /* Skip component slot if necessary */
6378     if (mat->stencil.noc) dxm++;
6379     /* Local row number */
6380     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6381   }
6382   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6383   PetscCall(PetscFree(jdxm));
6384   PetscFunctionReturn(PETSC_SUCCESS);
6385 }
6386 
6387 /*@
6388   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6389   of a set of rows and columns of a matrix.
6390 
6391   Collective
6392 
6393   Input Parameters:
6394 + mat     - the matrix
6395 . numRows - the number of rows/columns to remove
6396 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6397 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6398 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6399 - b       - optional vector of right hand side, that will be adjusted by provided solution
6400 
6401   Level: intermediate
6402 
6403   Notes:
6404   See `MatZeroRowsColumns()` for details on how this routine operates.
6405 
6406   The grid coordinates are across the entire grid, not just the local portion
6407 
6408   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6409   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6410   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6411   `DM_BOUNDARY_PERIODIC` boundary type.
6412 
6413   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
6414   a single value per point) you can skip filling those indices.
6415 
6416   Fortran Notes:
6417   `idxm` and `idxn` should be declared as
6418 $     MatStencil idxm(4, m)
6419   and the values inserted using
6420 .vb
6421     idxm(MatStencil_i, 1) = i
6422     idxm(MatStencil_j, 1) = j
6423     idxm(MatStencil_k, 1) = k
6424     idxm(MatStencil_c, 1) = c
6425     etc
6426 .ve
6427 
6428 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6429           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6430 @*/
6431 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6432 {
6433   PetscInt  dim    = mat->stencil.dim;
6434   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6435   PetscInt *dims   = mat->stencil.dims + 1;
6436   PetscInt *starts = mat->stencil.starts;
6437   PetscInt *dxm    = (PetscInt *)rows;
6438   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6439 
6440   PetscFunctionBegin;
6441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6442   PetscValidType(mat, 1);
6443   if (numRows) PetscAssertPointer(rows, 3);
6444 
6445   PetscCall(PetscMalloc1(numRows, &jdxm));
6446   for (i = 0; i < numRows; ++i) {
6447     /* Skip unused dimensions (they are ordered k, j, i, c) */
6448     for (j = 0; j < 3 - sdim; ++j) dxm++;
6449     /* Local index in X dir */
6450     tmp = *dxm++ - starts[0];
6451     /* Loop over remaining dimensions */
6452     for (j = 0; j < dim - 1; ++j) {
6453       /* If nonlocal, set index to be negative */
6454       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6455       /* Update local index */
6456       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6457     }
6458     /* Skip component slot if necessary */
6459     if (mat->stencil.noc) dxm++;
6460     /* Local row number */
6461     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6462   }
6463   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6464   PetscCall(PetscFree(jdxm));
6465   PetscFunctionReturn(PETSC_SUCCESS);
6466 }
6467 
6468 /*@C
6469   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6470   of a set of rows of a matrix; using local numbering of rows.
6471 
6472   Collective
6473 
6474   Input Parameters:
6475 + mat     - the matrix
6476 . numRows - the number of rows to remove
6477 . rows    - the local row indices
6478 . diag    - value put in all diagonals of eliminated rows
6479 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6480 - b       - optional vector of right hand side, that will be adjusted by provided solution
6481 
6482   Level: intermediate
6483 
6484   Notes:
6485   Before calling `MatZeroRowsLocal()`, the user must first set the
6486   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6487 
6488   See `MatZeroRows()` for details on how this routine operates.
6489 
6490 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6491           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6492 @*/
6493 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6494 {
6495   PetscFunctionBegin;
6496   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6497   PetscValidType(mat, 1);
6498   if (numRows) PetscAssertPointer(rows, 3);
6499   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6500   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6501   MatCheckPreallocated(mat, 1);
6502 
6503   if (mat->ops->zerorowslocal) {
6504     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6505   } else {
6506     IS              is, newis;
6507     const PetscInt *newRows;
6508 
6509     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6510     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6511     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6512     PetscCall(ISGetIndices(newis, &newRows));
6513     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6514     PetscCall(ISRestoreIndices(newis, &newRows));
6515     PetscCall(ISDestroy(&newis));
6516     PetscCall(ISDestroy(&is));
6517   }
6518   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6519   PetscFunctionReturn(PETSC_SUCCESS);
6520 }
6521 
6522 /*@
6523   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6524   of a set of rows of a matrix; using local numbering of rows.
6525 
6526   Collective
6527 
6528   Input Parameters:
6529 + mat  - the matrix
6530 . is   - index set of rows to remove
6531 . diag - value put in all diagonals of eliminated rows
6532 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6533 - b    - optional vector of right hand side, that will be adjusted by provided solution
6534 
6535   Level: intermediate
6536 
6537   Notes:
6538   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6539   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6540 
6541   See `MatZeroRows()` for details on how this routine operates.
6542 
6543 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6544           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6545 @*/
6546 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6547 {
6548   PetscInt        numRows;
6549   const PetscInt *rows;
6550 
6551   PetscFunctionBegin;
6552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6553   PetscValidType(mat, 1);
6554   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6556   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6557   MatCheckPreallocated(mat, 1);
6558 
6559   PetscCall(ISGetLocalSize(is, &numRows));
6560   PetscCall(ISGetIndices(is, &rows));
6561   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6562   PetscCall(ISRestoreIndices(is, &rows));
6563   PetscFunctionReturn(PETSC_SUCCESS);
6564 }
6565 
6566 /*@
6567   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6568   of a set of rows and columns of a matrix; using local numbering of rows.
6569 
6570   Collective
6571 
6572   Input Parameters:
6573 + mat     - the matrix
6574 . numRows - the number of rows to remove
6575 . rows    - the global row indices
6576 . diag    - value put in all diagonals of eliminated rows
6577 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6578 - b       - optional vector of right hand side, that will be adjusted by provided solution
6579 
6580   Level: intermediate
6581 
6582   Notes:
6583   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6584   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6585 
6586   See `MatZeroRowsColumns()` for details on how this routine operates.
6587 
6588 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6589           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6590 @*/
6591 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6592 {
6593   IS              is, newis;
6594   const PetscInt *newRows;
6595 
6596   PetscFunctionBegin;
6597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6598   PetscValidType(mat, 1);
6599   if (numRows) PetscAssertPointer(rows, 3);
6600   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6601   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6602   MatCheckPreallocated(mat, 1);
6603 
6604   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6605   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6606   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6607   PetscCall(ISGetIndices(newis, &newRows));
6608   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6609   PetscCall(ISRestoreIndices(newis, &newRows));
6610   PetscCall(ISDestroy(&newis));
6611   PetscCall(ISDestroy(&is));
6612   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6613   PetscFunctionReturn(PETSC_SUCCESS);
6614 }
6615 
6616 /*@
6617   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6618   of a set of rows and columns of a matrix; using local numbering of rows.
6619 
6620   Collective
6621 
6622   Input Parameters:
6623 + mat  - the matrix
6624 . is   - index set of rows to remove
6625 . diag - value put in all diagonals of eliminated rows
6626 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6627 - b    - optional vector of right hand side, that will be adjusted by provided solution
6628 
6629   Level: intermediate
6630 
6631   Notes:
6632   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6633   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6634 
6635   See `MatZeroRowsColumns()` for details on how this routine operates.
6636 
6637 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6638           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6639 @*/
6640 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6641 {
6642   PetscInt        numRows;
6643   const PetscInt *rows;
6644 
6645   PetscFunctionBegin;
6646   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6647   PetscValidType(mat, 1);
6648   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6651   MatCheckPreallocated(mat, 1);
6652 
6653   PetscCall(ISGetLocalSize(is, &numRows));
6654   PetscCall(ISGetIndices(is, &rows));
6655   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6656   PetscCall(ISRestoreIndices(is, &rows));
6657   PetscFunctionReturn(PETSC_SUCCESS);
6658 }
6659 
6660 /*@C
6661   MatGetSize - Returns the numbers of rows and columns in a matrix.
6662 
6663   Not Collective
6664 
6665   Input Parameter:
6666 . mat - the matrix
6667 
6668   Output Parameters:
6669 + m - the number of global rows
6670 - n - the number of global columns
6671 
6672   Level: beginner
6673 
6674   Note:
6675   Both output parameters can be `NULL` on input.
6676 
6677 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6678 @*/
6679 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6680 {
6681   PetscFunctionBegin;
6682   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6683   if (m) *m = mat->rmap->N;
6684   if (n) *n = mat->cmap->N;
6685   PetscFunctionReturn(PETSC_SUCCESS);
6686 }
6687 
6688 /*@C
6689   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6690   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6691 
6692   Not Collective
6693 
6694   Input Parameter:
6695 . mat - the matrix
6696 
6697   Output Parameters:
6698 + m - the number of local rows, use `NULL` to not obtain this value
6699 - n - the number of local columns, use `NULL` to not obtain this value
6700 
6701   Level: beginner
6702 
6703 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6704 @*/
6705 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6706 {
6707   PetscFunctionBegin;
6708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6709   if (m) PetscAssertPointer(m, 2);
6710   if (n) PetscAssertPointer(n, 3);
6711   if (m) *m = mat->rmap->n;
6712   if (n) *n = mat->cmap->n;
6713   PetscFunctionReturn(PETSC_SUCCESS);
6714 }
6715 
6716 /*@C
6717   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6718   vector one multiplies this matrix by that are owned by this processor.
6719 
6720   Not Collective, unless matrix has not been allocated, then collective
6721 
6722   Input Parameter:
6723 . mat - the matrix
6724 
6725   Output Parameters:
6726 + m - the global index of the first local column, use `NULL` to not obtain this value
6727 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6728 
6729   Level: developer
6730 
6731   Notes:
6732   Retursns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6733   Layouts](sec_matlayout) for details on matrix layouts.
6734 
6735 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6736 @*/
6737 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6738 {
6739   PetscFunctionBegin;
6740   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6741   PetscValidType(mat, 1);
6742   if (m) PetscAssertPointer(m, 2);
6743   if (n) PetscAssertPointer(n, 3);
6744   MatCheckPreallocated(mat, 1);
6745   if (m) *m = mat->cmap->rstart;
6746   if (n) *n = mat->cmap->rend;
6747   PetscFunctionReturn(PETSC_SUCCESS);
6748 }
6749 
6750 /*@C
6751   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6752   this MPI process.
6753 
6754   Not Collective
6755 
6756   Input Parameter:
6757 . mat - the matrix
6758 
6759   Output Parameters:
6760 + m - the global index of the first local row, use `NULL` to not obtain this value
6761 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6762 
6763   Level: beginner
6764 
6765   Note:
6766   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6767   would contain the result of a matrix vector product with this matrix. See [Matrix
6768   Layouts](sec_matlayout) for details on matrix layouts.
6769 
6770 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6771           `PetscLayout`
6772 @*/
6773 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6774 {
6775   PetscFunctionBegin;
6776   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6777   PetscValidType(mat, 1);
6778   if (m) PetscAssertPointer(m, 2);
6779   if (n) PetscAssertPointer(n, 3);
6780   MatCheckPreallocated(mat, 1);
6781   if (m) *m = mat->rmap->rstart;
6782   if (n) *n = mat->rmap->rend;
6783   PetscFunctionReturn(PETSC_SUCCESS);
6784 }
6785 
6786 /*@C
6787   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6788   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6789 
6790   Not Collective, unless matrix has not been allocated
6791 
6792   Input Parameter:
6793 . mat - the matrix
6794 
6795   Output Parameter:
6796 . ranges - start of each processors portion plus one more than the total length at the end
6797 
6798   Level: beginner
6799 
6800   Notes:
6801   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6802   would contain the result of a matrix vector product with this matrix. See [Matrix
6803   Layouts](sec_matlayout) for details on matrix layouts.
6804 
6805 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6806 @*/
6807 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6808 {
6809   PetscFunctionBegin;
6810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6811   PetscValidType(mat, 1);
6812   MatCheckPreallocated(mat, 1);
6813   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6814   PetscFunctionReturn(PETSC_SUCCESS);
6815 }
6816 
6817 /*@C
6818   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6819   vector one multiplies this vector by that are owned by each processor.
6820 
6821   Not Collective, unless matrix has not been allocated
6822 
6823   Input Parameter:
6824 . mat - the matrix
6825 
6826   Output Parameter:
6827 . ranges - start of each processors portion plus one more then the total length at the end
6828 
6829   Level: beginner
6830 
6831   Notes:
6832   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6833   Layouts](sec_matlayout) for details on matrix layouts.
6834 
6835 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6836 @*/
6837 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6838 {
6839   PetscFunctionBegin;
6840   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6841   PetscValidType(mat, 1);
6842   MatCheckPreallocated(mat, 1);
6843   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6844   PetscFunctionReturn(PETSC_SUCCESS);
6845 }
6846 
6847 /*@C
6848   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6849 
6850   Not Collective
6851 
6852   Input Parameter:
6853 . A - matrix
6854 
6855   Output Parameters:
6856 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6857 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6858 
6859   Level: intermediate
6860 
6861   Notes:
6862   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6863   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6864   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6865   details on matrix layouts.
6866 
6867 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6868 @*/
6869 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6870 {
6871   PetscErrorCode (*f)(Mat, IS *, IS *);
6872 
6873   PetscFunctionBegin;
6874   MatCheckPreallocated(A, 1);
6875   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6876   if (f) {
6877     PetscCall((*f)(A, rows, cols));
6878   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6879     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6880     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6881   }
6882   PetscFunctionReturn(PETSC_SUCCESS);
6883 }
6884 
6885 /*@C
6886   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6887   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6888   to complete the factorization.
6889 
6890   Collective
6891 
6892   Input Parameters:
6893 + fact - the factorized matrix obtained with `MatGetFactor()`
6894 . mat  - the matrix
6895 . row  - row permutation
6896 . col  - column permutation
6897 - info - structure containing
6898 .vb
6899       levels - number of levels of fill.
6900       expected fill - as ratio of original fill.
6901       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6902                 missing diagonal entries)
6903 .ve
6904 
6905   Level: developer
6906 
6907   Notes:
6908   See [Matrix Factorization](sec_matfactor) for additional information.
6909 
6910   Most users should employ the `KSP` interface for linear solvers
6911   instead of working directly with matrix algebra routines such as this.
6912   See, e.g., `KSPCreate()`.
6913 
6914   Uses the definition of level of fill as in Y. Saad, 2003
6915 
6916   Developer Notes:
6917   The Fortran interface is not autogenerated as the
6918   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6919 
6920   References:
6921 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6922 
6923 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6924           `MatGetOrdering()`, `MatFactorInfo`
6925 @*/
6926 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6927 {
6928   PetscFunctionBegin;
6929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6930   PetscValidType(mat, 2);
6931   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6932   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6933   PetscAssertPointer(info, 5);
6934   PetscAssertPointer(fact, 1);
6935   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6936   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6937   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6938   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6939   MatCheckPreallocated(mat, 2);
6940 
6941   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6942   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6943   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6944   PetscFunctionReturn(PETSC_SUCCESS);
6945 }
6946 
6947 /*@C
6948   MatICCFactorSymbolic - Performs symbolic incomplete
6949   Cholesky factorization for a symmetric matrix.  Use
6950   `MatCholeskyFactorNumeric()` to complete the factorization.
6951 
6952   Collective
6953 
6954   Input Parameters:
6955 + fact - the factorized matrix obtained with `MatGetFactor()`
6956 . mat  - the matrix to be factored
6957 . perm - row and column permutation
6958 - info - structure containing
6959 .vb
6960       levels - number of levels of fill.
6961       expected fill - as ratio of original fill.
6962 .ve
6963 
6964   Level: developer
6965 
6966   Notes:
6967   Most users should employ the `KSP` interface for linear solvers
6968   instead of working directly with matrix algebra routines such as this.
6969   See, e.g., `KSPCreate()`.
6970 
6971   This uses the definition of level of fill as in Y. Saad, 2003
6972 
6973   Developer Notes:
6974   The Fortran interface is not autogenerated as the
6975   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6976 
6977   References:
6978 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6979 
6980 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6981 @*/
6982 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6983 {
6984   PetscFunctionBegin;
6985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6986   PetscValidType(mat, 2);
6987   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6988   PetscAssertPointer(info, 4);
6989   PetscAssertPointer(fact, 1);
6990   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6991   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6992   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6993   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6994   MatCheckPreallocated(mat, 2);
6995 
6996   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6997   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6998   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6999   PetscFunctionReturn(PETSC_SUCCESS);
7000 }
7001 
7002 /*@C
7003   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7004   points to an array of valid matrices, they may be reused to store the new
7005   submatrices.
7006 
7007   Collective
7008 
7009   Input Parameters:
7010 + mat   - the matrix
7011 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7012 . irow  - index set of rows to extract
7013 . icol  - index set of columns to extract
7014 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7015 
7016   Output Parameter:
7017 . submat - the array of submatrices
7018 
7019   Level: advanced
7020 
7021   Notes:
7022   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7023   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7024   to extract a parallel submatrix.
7025 
7026   Some matrix types place restrictions on the row and column
7027   indices, such as that they be sorted or that they be equal to each other.
7028 
7029   The index sets may not have duplicate entries.
7030 
7031   When extracting submatrices from a parallel matrix, each processor can
7032   form a different submatrix by setting the rows and columns of its
7033   individual index sets according to the local submatrix desired.
7034 
7035   When finished using the submatrices, the user should destroy
7036   them with `MatDestroySubMatrices()`.
7037 
7038   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7039   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7040 
7041   This routine creates the matrices in submat; you should NOT create them before
7042   calling it. It also allocates the array of matrix pointers submat.
7043 
7044   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7045   request one row/column in a block, they must request all rows/columns that are in
7046   that block. For example, if the block size is 2 you cannot request just row 0 and
7047   column 0.
7048 
7049   Fortran Notes:
7050   The Fortran interface is slightly different from that given below; it
7051   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7052 
7053 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7054 @*/
7055 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7056 {
7057   PetscInt  i;
7058   PetscBool eq;
7059 
7060   PetscFunctionBegin;
7061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7062   PetscValidType(mat, 1);
7063   if (n) {
7064     PetscAssertPointer(irow, 3);
7065     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7066     PetscAssertPointer(icol, 4);
7067     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7068   }
7069   PetscAssertPointer(submat, 6);
7070   if (n && scall == MAT_REUSE_MATRIX) {
7071     PetscAssertPointer(*submat, 6);
7072     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7073   }
7074   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7075   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7076   MatCheckPreallocated(mat, 1);
7077   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7078   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7079   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7080   for (i = 0; i < n; i++) {
7081     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7082     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7083     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7084 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7085     if (mat->boundtocpu && mat->bindingpropagates) {
7086       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7087       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7088     }
7089 #endif
7090   }
7091   PetscFunctionReturn(PETSC_SUCCESS);
7092 }
7093 
7094 /*@C
7095   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7096 
7097   Collective
7098 
7099   Input Parameters:
7100 + mat   - the matrix
7101 . n     - the number of submatrixes to be extracted
7102 . irow  - index set of rows to extract
7103 . icol  - index set of columns to extract
7104 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7105 
7106   Output Parameter:
7107 . submat - the array of submatrices
7108 
7109   Level: advanced
7110 
7111   Note:
7112   This is used by `PCGASM`
7113 
7114 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7115 @*/
7116 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7117 {
7118   PetscInt  i;
7119   PetscBool eq;
7120 
7121   PetscFunctionBegin;
7122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7123   PetscValidType(mat, 1);
7124   if (n) {
7125     PetscAssertPointer(irow, 3);
7126     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7127     PetscAssertPointer(icol, 4);
7128     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7129   }
7130   PetscAssertPointer(submat, 6);
7131   if (n && scall == MAT_REUSE_MATRIX) {
7132     PetscAssertPointer(*submat, 6);
7133     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7134   }
7135   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7136   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7137   MatCheckPreallocated(mat, 1);
7138 
7139   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7140   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7141   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7142   for (i = 0; i < n; i++) {
7143     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7144     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7145   }
7146   PetscFunctionReturn(PETSC_SUCCESS);
7147 }
7148 
7149 /*@C
7150   MatDestroyMatrices - Destroys an array of matrices.
7151 
7152   Collective
7153 
7154   Input Parameters:
7155 + n   - the number of local matrices
7156 - mat - the matrices (this is a pointer to the array of matrices)
7157 
7158   Level: advanced
7159 
7160   Note:
7161   Frees not only the matrices, but also the array that contains the matrices
7162 
7163   Fortran Notes:
7164   This does not free the array.
7165 
7166 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7167 @*/
7168 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7169 {
7170   PetscInt i;
7171 
7172   PetscFunctionBegin;
7173   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7174   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7175   PetscAssertPointer(mat, 2);
7176 
7177   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7178 
7179   /* memory is allocated even if n = 0 */
7180   PetscCall(PetscFree(*mat));
7181   PetscFunctionReturn(PETSC_SUCCESS);
7182 }
7183 
7184 /*@C
7185   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7186 
7187   Collective
7188 
7189   Input Parameters:
7190 + n   - the number of local matrices
7191 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7192                        sequence of `MatCreateSubMatrices()`)
7193 
7194   Level: advanced
7195 
7196   Note:
7197   Frees not only the matrices, but also the array that contains the matrices
7198 
7199   Fortran Notes:
7200   This does not free the array.
7201 
7202 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7203 @*/
7204 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7205 {
7206   Mat mat0;
7207 
7208   PetscFunctionBegin;
7209   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7210   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7211   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7212   PetscAssertPointer(mat, 2);
7213 
7214   mat0 = (*mat)[0];
7215   if (mat0 && mat0->ops->destroysubmatrices) {
7216     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7217   } else {
7218     PetscCall(MatDestroyMatrices(n, mat));
7219   }
7220   PetscFunctionReturn(PETSC_SUCCESS);
7221 }
7222 
7223 /*@C
7224   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7225 
7226   Collective
7227 
7228   Input Parameter:
7229 . mat - the matrix
7230 
7231   Output Parameter:
7232 . matstruct - the sequential matrix with the nonzero structure of mat
7233 
7234   Level: developer
7235 
7236 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7237 @*/
7238 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7239 {
7240   PetscFunctionBegin;
7241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7242   PetscAssertPointer(matstruct, 2);
7243 
7244   PetscValidType(mat, 1);
7245   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7246   MatCheckPreallocated(mat, 1);
7247 
7248   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7249   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7250   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7251   PetscFunctionReturn(PETSC_SUCCESS);
7252 }
7253 
7254 /*@C
7255   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7256 
7257   Collective
7258 
7259   Input Parameter:
7260 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7261                        sequence of `MatGetSeqNonzeroStructure()`)
7262 
7263   Level: advanced
7264 
7265   Note:
7266   Frees not only the matrices, but also the array that contains the matrices
7267 
7268 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7269 @*/
7270 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7271 {
7272   PetscFunctionBegin;
7273   PetscAssertPointer(mat, 1);
7274   PetscCall(MatDestroy(mat));
7275   PetscFunctionReturn(PETSC_SUCCESS);
7276 }
7277 
7278 /*@
7279   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7280   replaces the index sets by larger ones that represent submatrices with
7281   additional overlap.
7282 
7283   Collective
7284 
7285   Input Parameters:
7286 + mat - the matrix
7287 . n   - the number of index sets
7288 . is  - the array of index sets (these index sets will changed during the call)
7289 - ov  - the additional overlap requested
7290 
7291   Options Database Key:
7292 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7293 
7294   Level: developer
7295 
7296   Note:
7297   The computed overlap preserves the matrix block sizes when the blocks are square.
7298   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7299   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7300 
7301 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7302 @*/
7303 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7304 {
7305   PetscInt i, bs, cbs;
7306 
7307   PetscFunctionBegin;
7308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7309   PetscValidType(mat, 1);
7310   PetscValidLogicalCollectiveInt(mat, n, 2);
7311   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7312   if (n) {
7313     PetscAssertPointer(is, 3);
7314     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7315   }
7316   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7317   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7318   MatCheckPreallocated(mat, 1);
7319 
7320   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7321   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7322   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7323   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7324   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7325   if (bs == cbs) {
7326     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7327   }
7328   PetscFunctionReturn(PETSC_SUCCESS);
7329 }
7330 
7331 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7332 
7333 /*@
7334   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7335   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7336   additional overlap.
7337 
7338   Collective
7339 
7340   Input Parameters:
7341 + mat - the matrix
7342 . n   - the number of index sets
7343 . is  - the array of index sets (these index sets will changed during the call)
7344 - ov  - the additional overlap requested
7345 
7346   `   Options Database Key:
7347 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7348 
7349   Level: developer
7350 
7351 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7352 @*/
7353 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7354 {
7355   PetscInt i;
7356 
7357   PetscFunctionBegin;
7358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7359   PetscValidType(mat, 1);
7360   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7361   if (n) {
7362     PetscAssertPointer(is, 3);
7363     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7364   }
7365   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7366   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7367   MatCheckPreallocated(mat, 1);
7368   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7369   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7370   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7371   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7372   PetscFunctionReturn(PETSC_SUCCESS);
7373 }
7374 
7375 /*@
7376   MatGetBlockSize - Returns the matrix block size.
7377 
7378   Not Collective
7379 
7380   Input Parameter:
7381 . mat - the matrix
7382 
7383   Output Parameter:
7384 . bs - block size
7385 
7386   Level: intermediate
7387 
7388   Notes:
7389   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7390 
7391   If the block size has not been set yet this routine returns 1.
7392 
7393 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7394 @*/
7395 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7396 {
7397   PetscFunctionBegin;
7398   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7399   PetscAssertPointer(bs, 2);
7400   *bs = PetscAbs(mat->rmap->bs);
7401   PetscFunctionReturn(PETSC_SUCCESS);
7402 }
7403 
7404 /*@
7405   MatGetBlockSizes - Returns the matrix block row and column sizes.
7406 
7407   Not Collective
7408 
7409   Input Parameter:
7410 . mat - the matrix
7411 
7412   Output Parameters:
7413 + rbs - row block size
7414 - cbs - column block size
7415 
7416   Level: intermediate
7417 
7418   Notes:
7419   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7420   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7421 
7422   If a block size has not been set yet this routine returns 1.
7423 
7424 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7425 @*/
7426 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7427 {
7428   PetscFunctionBegin;
7429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7430   if (rbs) PetscAssertPointer(rbs, 2);
7431   if (cbs) PetscAssertPointer(cbs, 3);
7432   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7433   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7434   PetscFunctionReturn(PETSC_SUCCESS);
7435 }
7436 
7437 /*@
7438   MatSetBlockSize - Sets the matrix block size.
7439 
7440   Logically Collective
7441 
7442   Input Parameters:
7443 + mat - the matrix
7444 - bs  - block size
7445 
7446   Level: intermediate
7447 
7448   Notes:
7449   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7450   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7451 
7452   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7453   is compatible with the matrix local sizes.
7454 
7455 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7456 @*/
7457 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7458 {
7459   PetscFunctionBegin;
7460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7461   PetscValidLogicalCollectiveInt(mat, bs, 2);
7462   PetscCall(MatSetBlockSizes(mat, bs, bs));
7463   PetscFunctionReturn(PETSC_SUCCESS);
7464 }
7465 
7466 typedef struct {
7467   PetscInt         n;
7468   IS              *is;
7469   Mat             *mat;
7470   PetscObjectState nonzerostate;
7471   Mat              C;
7472 } EnvelopeData;
7473 
7474 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7475 {
7476   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7477   PetscCall(PetscFree(edata->is));
7478   PetscCall(PetscFree(edata));
7479   return PETSC_SUCCESS;
7480 }
7481 
7482 /*@
7483   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7484   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7485 
7486   Collective
7487 
7488   Input Parameter:
7489 . mat - the matrix
7490 
7491   Level: intermediate
7492 
7493   Notes:
7494   There can be zeros within the blocks
7495 
7496   The blocks can overlap between processes, including laying on more than two processes
7497 
7498 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7499 @*/
7500 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7501 {
7502   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7503   PetscInt          *diag, *odiag, sc;
7504   VecScatter         scatter;
7505   PetscScalar       *seqv;
7506   const PetscScalar *parv;
7507   const PetscInt    *ia, *ja;
7508   PetscBool          set, flag, done;
7509   Mat                AA = mat, A;
7510   MPI_Comm           comm;
7511   PetscMPIInt        rank, size, tag;
7512   MPI_Status         status;
7513   PetscContainer     container;
7514   EnvelopeData      *edata;
7515   Vec                seq, par;
7516   IS                 isglobal;
7517 
7518   PetscFunctionBegin;
7519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7520   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7521   if (!set || !flag) {
7522     /* TODO: only needs nonzero structure of transpose */
7523     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7524     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7525   }
7526   PetscCall(MatAIJGetLocalMat(AA, &A));
7527   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7528   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7529 
7530   PetscCall(MatGetLocalSize(mat, &n, NULL));
7531   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7532   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7533   PetscCallMPI(MPI_Comm_size(comm, &size));
7534   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7535 
7536   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7537 
7538   if (rank > 0) {
7539     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7540     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7541   }
7542   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7543   for (i = 0; i < n; i++) {
7544     env = PetscMax(env, ja[ia[i + 1] - 1]);
7545     II  = rstart + i;
7546     if (env == II) {
7547       starts[lblocks]  = tbs;
7548       sizes[lblocks++] = 1 + II - tbs;
7549       tbs              = 1 + II;
7550     }
7551   }
7552   if (rank < size - 1) {
7553     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7554     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7555   }
7556 
7557   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7558   if (!set || !flag) PetscCall(MatDestroy(&AA));
7559   PetscCall(MatDestroy(&A));
7560 
7561   PetscCall(PetscNew(&edata));
7562   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7563   edata->n = lblocks;
7564   /* create IS needed for extracting blocks from the original matrix */
7565   PetscCall(PetscMalloc1(lblocks, &edata->is));
7566   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7567 
7568   /* Create the resulting inverse matrix structure with preallocation information */
7569   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7570   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7571   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7572   PetscCall(MatSetType(edata->C, MATAIJ));
7573 
7574   /* Communicate the start and end of each row, from each block to the correct rank */
7575   /* TODO: Use PetscSF instead of VecScatter */
7576   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7577   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7578   PetscCall(VecGetArrayWrite(seq, &seqv));
7579   for (PetscInt i = 0; i < lblocks; i++) {
7580     for (PetscInt j = 0; j < sizes[i]; j++) {
7581       seqv[cnt]     = starts[i];
7582       seqv[cnt + 1] = starts[i] + sizes[i];
7583       cnt += 2;
7584     }
7585   }
7586   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7587   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7588   sc -= cnt;
7589   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7590   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7591   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7592   PetscCall(ISDestroy(&isglobal));
7593   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7594   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7595   PetscCall(VecScatterDestroy(&scatter));
7596   PetscCall(VecDestroy(&seq));
7597   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7598   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7599   PetscCall(VecGetArrayRead(par, &parv));
7600   cnt = 0;
7601   PetscCall(MatGetSize(mat, NULL, &n));
7602   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7603     PetscInt start, end, d = 0, od = 0;
7604 
7605     start = (PetscInt)PetscRealPart(parv[cnt]);
7606     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7607     cnt += 2;
7608 
7609     if (start < cstart) {
7610       od += cstart - start + n - cend;
7611       d += cend - cstart;
7612     } else if (start < cend) {
7613       od += n - cend;
7614       d += cend - start;
7615     } else od += n - start;
7616     if (end <= cstart) {
7617       od -= cstart - end + n - cend;
7618       d -= cend - cstart;
7619     } else if (end < cend) {
7620       od -= n - cend;
7621       d -= cend - end;
7622     } else od -= n - end;
7623 
7624     odiag[i] = od;
7625     diag[i]  = d;
7626   }
7627   PetscCall(VecRestoreArrayRead(par, &parv));
7628   PetscCall(VecDestroy(&par));
7629   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7630   PetscCall(PetscFree2(diag, odiag));
7631   PetscCall(PetscFree2(sizes, starts));
7632 
7633   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7634   PetscCall(PetscContainerSetPointer(container, edata));
7635   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7636   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7637   PetscCall(PetscObjectDereference((PetscObject)container));
7638   PetscFunctionReturn(PETSC_SUCCESS);
7639 }
7640 
7641 /*@
7642   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7643 
7644   Collective
7645 
7646   Input Parameters:
7647 + A     - the matrix
7648 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7649 
7650   Output Parameter:
7651 . C - matrix with inverted block diagonal of `A`
7652 
7653   Level: advanced
7654 
7655   Note:
7656   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7657 
7658 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7659 @*/
7660 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7661 {
7662   PetscContainer   container;
7663   EnvelopeData    *edata;
7664   PetscObjectState nonzerostate;
7665 
7666   PetscFunctionBegin;
7667   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7668   if (!container) {
7669     PetscCall(MatComputeVariableBlockEnvelope(A));
7670     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7671   }
7672   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7673   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7674   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7675   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7676 
7677   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7678   *C = edata->C;
7679 
7680   for (PetscInt i = 0; i < edata->n; i++) {
7681     Mat          D;
7682     PetscScalar *dvalues;
7683 
7684     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7685     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7686     PetscCall(MatSeqDenseInvert(D));
7687     PetscCall(MatDenseGetArray(D, &dvalues));
7688     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7689     PetscCall(MatDestroy(&D));
7690   }
7691   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7692   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7693   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7694   PetscFunctionReturn(PETSC_SUCCESS);
7695 }
7696 
7697 /*@
7698   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7699 
7700   Logically Collective
7701 
7702   Input Parameters:
7703 + mat     - the matrix
7704 . nblocks - the number of blocks on this process, each block can only exist on a single process
7705 - bsizes  - the block sizes
7706 
7707   Level: intermediate
7708 
7709   Notes:
7710   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7711 
7712   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.
7713 
7714 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7715           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7716 @*/
7717 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7718 {
7719   PetscInt i, ncnt = 0, nlocal;
7720 
7721   PetscFunctionBegin;
7722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7723   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7724   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7725   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7726   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);
7727   PetscCall(PetscFree(mat->bsizes));
7728   mat->nblocks = nblocks;
7729   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7730   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7731   PetscFunctionReturn(PETSC_SUCCESS);
7732 }
7733 
7734 /*@C
7735   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7736 
7737   Logically Collective; No Fortran Support
7738 
7739   Input Parameter:
7740 . mat - the matrix
7741 
7742   Output Parameters:
7743 + nblocks - the number of blocks on this process
7744 - bsizes  - the block sizes
7745 
7746   Level: intermediate
7747 
7748 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7749 @*/
7750 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7751 {
7752   PetscFunctionBegin;
7753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7754   *nblocks = mat->nblocks;
7755   *bsizes  = mat->bsizes;
7756   PetscFunctionReturn(PETSC_SUCCESS);
7757 }
7758 
7759 /*@
7760   MatSetBlockSizes - Sets the matrix block row and column sizes.
7761 
7762   Logically Collective
7763 
7764   Input Parameters:
7765 + mat - the matrix
7766 . rbs - row block size
7767 - cbs - column block size
7768 
7769   Level: intermediate
7770 
7771   Notes:
7772   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7773   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7774   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7775 
7776   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7777   are compatible with the matrix local sizes.
7778 
7779   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7780 
7781 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7782 @*/
7783 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7784 {
7785   PetscFunctionBegin;
7786   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7787   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7788   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7789   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7790   if (mat->rmap->refcnt) {
7791     ISLocalToGlobalMapping l2g  = NULL;
7792     PetscLayout            nmap = NULL;
7793 
7794     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7795     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7796     PetscCall(PetscLayoutDestroy(&mat->rmap));
7797     mat->rmap          = nmap;
7798     mat->rmap->mapping = l2g;
7799   }
7800   if (mat->cmap->refcnt) {
7801     ISLocalToGlobalMapping l2g  = NULL;
7802     PetscLayout            nmap = NULL;
7803 
7804     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7805     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7806     PetscCall(PetscLayoutDestroy(&mat->cmap));
7807     mat->cmap          = nmap;
7808     mat->cmap->mapping = l2g;
7809   }
7810   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7811   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7812   PetscFunctionReturn(PETSC_SUCCESS);
7813 }
7814 
7815 /*@
7816   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7817 
7818   Logically Collective
7819 
7820   Input Parameters:
7821 + mat     - the matrix
7822 . fromRow - matrix from which to copy row block size
7823 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7824 
7825   Level: developer
7826 
7827 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7828 @*/
7829 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7830 {
7831   PetscFunctionBegin;
7832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7833   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7834   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7835   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7836   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7837   PetscFunctionReturn(PETSC_SUCCESS);
7838 }
7839 
7840 /*@
7841   MatResidual - Default routine to calculate the residual r = b - Ax
7842 
7843   Collective
7844 
7845   Input Parameters:
7846 + mat - the matrix
7847 . b   - the right-hand-side
7848 - x   - the approximate solution
7849 
7850   Output Parameter:
7851 . r - location to store the residual
7852 
7853   Level: developer
7854 
7855 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7856 @*/
7857 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7858 {
7859   PetscFunctionBegin;
7860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7861   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7862   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7863   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7864   PetscValidType(mat, 1);
7865   MatCheckPreallocated(mat, 1);
7866   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7867   if (!mat->ops->residual) {
7868     PetscCall(MatMult(mat, x, r));
7869     PetscCall(VecAYPX(r, -1.0, b));
7870   } else {
7871     PetscUseTypeMethod(mat, residual, b, x, r);
7872   }
7873   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7874   PetscFunctionReturn(PETSC_SUCCESS);
7875 }
7876 
7877 /*MC
7878     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7879 
7880     Synopsis:
7881     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7882 
7883     Not Collective
7884 
7885     Input Parameters:
7886 +   A - the matrix
7887 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7888 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7889 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7890                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7891                  always used.
7892 
7893     Output Parameters:
7894 +   n - number of local rows in the (possibly compressed) matrix
7895 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7896 .   ja - the column indices
7897 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7898            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7899 
7900     Level: developer
7901 
7902     Note:
7903     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7904 
7905 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7906 M*/
7907 
7908 /*MC
7909     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7910 
7911     Synopsis:
7912     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7913 
7914     Not Collective
7915 
7916     Input Parameters:
7917 +   A - the  matrix
7918 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7919 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7920     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7921                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7922                  always used.
7923 .   n - number of local rows in the (possibly compressed) matrix
7924 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7925 .   ja - the column indices
7926 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7927            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7928 
7929     Level: developer
7930 
7931 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7932 M*/
7933 
7934 /*@C
7935   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7936 
7937   Collective
7938 
7939   Input Parameters:
7940 + mat             - the matrix
7941 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7942 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7943 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7944                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7945                  always used.
7946 
7947   Output Parameters:
7948 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7949 . 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
7950 . ja   - the column indices, use `NULL` if not needed
7951 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7952            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7953 
7954   Level: developer
7955 
7956   Notes:
7957   You CANNOT change any of the ia[] or ja[] values.
7958 
7959   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7960 
7961   Fortran Notes:
7962   Use
7963 .vb
7964     PetscInt, pointer :: ia(:),ja(:)
7965     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7966     ! Access the ith and jth entries via ia(i) and ja(j)
7967 .ve
7968   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7969 
7970 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7971 @*/
7972 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7973 {
7974   PetscFunctionBegin;
7975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7976   PetscValidType(mat, 1);
7977   if (n) PetscAssertPointer(n, 5);
7978   if (ia) PetscAssertPointer(ia, 6);
7979   if (ja) PetscAssertPointer(ja, 7);
7980   if (done) PetscAssertPointer(done, 8);
7981   MatCheckPreallocated(mat, 1);
7982   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7983   else {
7984     if (done) *done = PETSC_TRUE;
7985     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7986     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7987     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7988   }
7989   PetscFunctionReturn(PETSC_SUCCESS);
7990 }
7991 
7992 /*@C
7993   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7994 
7995   Collective
7996 
7997   Input Parameters:
7998 + mat             - the matrix
7999 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8000 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8001                 symmetrized
8002 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8003                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8004                  always used.
8005 . n               - number of columns in the (possibly compressed) matrix
8006 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8007 - ja              - the row indices
8008 
8009   Output Parameter:
8010 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8011 
8012   Level: developer
8013 
8014 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8015 @*/
8016 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8017 {
8018   PetscFunctionBegin;
8019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8020   PetscValidType(mat, 1);
8021   PetscAssertPointer(n, 5);
8022   if (ia) PetscAssertPointer(ia, 6);
8023   if (ja) PetscAssertPointer(ja, 7);
8024   PetscAssertPointer(done, 8);
8025   MatCheckPreallocated(mat, 1);
8026   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8027   else {
8028     *done = PETSC_TRUE;
8029     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8030   }
8031   PetscFunctionReturn(PETSC_SUCCESS);
8032 }
8033 
8034 /*@C
8035   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8036 
8037   Collective
8038 
8039   Input Parameters:
8040 + mat             - the matrix
8041 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8042 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8043 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8044                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8045                  always used.
8046 . n               - size of (possibly compressed) matrix
8047 . ia              - the row pointers
8048 - ja              - the column indices
8049 
8050   Output Parameter:
8051 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8052 
8053   Level: developer
8054 
8055   Note:
8056   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8057   us of the array after it has been restored. If you pass `NULL`, it will
8058   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8059 
8060   Fortran Notes:
8061   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8062 
8063 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8064 @*/
8065 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8066 {
8067   PetscFunctionBegin;
8068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8069   PetscValidType(mat, 1);
8070   if (ia) PetscAssertPointer(ia, 6);
8071   if (ja) PetscAssertPointer(ja, 7);
8072   if (done) PetscAssertPointer(done, 8);
8073   MatCheckPreallocated(mat, 1);
8074 
8075   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8076   else {
8077     if (done) *done = PETSC_TRUE;
8078     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8079     if (n) *n = 0;
8080     if (ia) *ia = NULL;
8081     if (ja) *ja = NULL;
8082   }
8083   PetscFunctionReturn(PETSC_SUCCESS);
8084 }
8085 
8086 /*@C
8087   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8088 
8089   Collective
8090 
8091   Input Parameters:
8092 + mat             - the matrix
8093 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8094 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8095 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8096                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8097                  always used.
8098 
8099   Output Parameters:
8100 + n    - size of (possibly compressed) matrix
8101 . ia   - the column pointers
8102 . ja   - the row indices
8103 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8104 
8105   Level: developer
8106 
8107 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8108 @*/
8109 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8110 {
8111   PetscFunctionBegin;
8112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8113   PetscValidType(mat, 1);
8114   if (ia) PetscAssertPointer(ia, 6);
8115   if (ja) PetscAssertPointer(ja, 7);
8116   PetscAssertPointer(done, 8);
8117   MatCheckPreallocated(mat, 1);
8118 
8119   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8120   else {
8121     *done = PETSC_TRUE;
8122     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8123     if (n) *n = 0;
8124     if (ia) *ia = NULL;
8125     if (ja) *ja = NULL;
8126   }
8127   PetscFunctionReturn(PETSC_SUCCESS);
8128 }
8129 
8130 /*@C
8131   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8132   `MatGetColumnIJ()`.
8133 
8134   Collective
8135 
8136   Input Parameters:
8137 + mat        - the matrix
8138 . ncolors    - maximum color value
8139 . n          - number of entries in colorarray
8140 - colorarray - array indicating color for each column
8141 
8142   Output Parameter:
8143 . iscoloring - coloring generated using colorarray information
8144 
8145   Level: developer
8146 
8147 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8148 @*/
8149 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8150 {
8151   PetscFunctionBegin;
8152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8153   PetscValidType(mat, 1);
8154   PetscAssertPointer(colorarray, 4);
8155   PetscAssertPointer(iscoloring, 5);
8156   MatCheckPreallocated(mat, 1);
8157 
8158   if (!mat->ops->coloringpatch) {
8159     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8160   } else {
8161     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8162   }
8163   PetscFunctionReturn(PETSC_SUCCESS);
8164 }
8165 
8166 /*@
8167   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8168 
8169   Logically Collective
8170 
8171   Input Parameter:
8172 . mat - the factored matrix to be reset
8173 
8174   Level: developer
8175 
8176   Notes:
8177   This routine should be used only with factored matrices formed by in-place
8178   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8179   format).  This option can save memory, for example, when solving nonlinear
8180   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8181   ILU(0) preconditioner.
8182 
8183   One can specify in-place ILU(0) factorization by calling
8184 .vb
8185      PCType(pc,PCILU);
8186      PCFactorSeUseInPlace(pc);
8187 .ve
8188   or by using the options -pc_type ilu -pc_factor_in_place
8189 
8190   In-place factorization ILU(0) can also be used as a local
8191   solver for the blocks within the block Jacobi or additive Schwarz
8192   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8193   for details on setting local solver options.
8194 
8195   Most users should employ the `KSP` interface for linear solvers
8196   instead of working directly with matrix algebra routines such as this.
8197   See, e.g., `KSPCreate()`.
8198 
8199 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8200 @*/
8201 PetscErrorCode MatSetUnfactored(Mat mat)
8202 {
8203   PetscFunctionBegin;
8204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8205   PetscValidType(mat, 1);
8206   MatCheckPreallocated(mat, 1);
8207   mat->factortype = MAT_FACTOR_NONE;
8208   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8209   PetscUseTypeMethod(mat, setunfactored);
8210   PetscFunctionReturn(PETSC_SUCCESS);
8211 }
8212 
8213 /*MC
8214     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8215 
8216     Synopsis:
8217     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8218 
8219     Not Collective
8220 
8221     Input Parameter:
8222 .   x - matrix
8223 
8224     Output Parameters:
8225 +   xx_v - the Fortran pointer to the array
8226 -   ierr - error code
8227 
8228     Example of Usage:
8229 .vb
8230       PetscScalar, pointer xx_v(:,:)
8231       ....
8232       call MatDenseGetArrayF90(x,xx_v,ierr)
8233       a = xx_v(3)
8234       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8235 .ve
8236 
8237     Level: advanced
8238 
8239 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8240 M*/
8241 
8242 /*MC
8243     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8244     accessed with `MatDenseGetArrayF90()`.
8245 
8246     Synopsis:
8247     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8248 
8249     Not Collective
8250 
8251     Input Parameters:
8252 +   x - matrix
8253 -   xx_v - the Fortran90 pointer to the array
8254 
8255     Output Parameter:
8256 .   ierr - error code
8257 
8258     Example of Usage:
8259 .vb
8260        PetscScalar, pointer xx_v(:,:)
8261        ....
8262        call MatDenseGetArrayF90(x,xx_v,ierr)
8263        a = xx_v(3)
8264        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8265 .ve
8266 
8267     Level: advanced
8268 
8269 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8270 M*/
8271 
8272 /*MC
8273     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8274 
8275     Synopsis:
8276     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8277 
8278     Not Collective
8279 
8280     Input Parameter:
8281 .   x - matrix
8282 
8283     Output Parameters:
8284 +   xx_v - the Fortran pointer to the array
8285 -   ierr - error code
8286 
8287     Example of Usage:
8288 .vb
8289       PetscScalar, pointer xx_v(:)
8290       ....
8291       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8292       a = xx_v(3)
8293       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8294 .ve
8295 
8296     Level: advanced
8297 
8298 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8299 M*/
8300 
8301 /*MC
8302     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8303     accessed with `MatSeqAIJGetArrayF90()`.
8304 
8305     Synopsis:
8306     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8307 
8308     Not Collective
8309 
8310     Input Parameters:
8311 +   x - matrix
8312 -   xx_v - the Fortran90 pointer to the array
8313 
8314     Output Parameter:
8315 .   ierr - error code
8316 
8317     Example of Usage:
8318 .vb
8319        PetscScalar, pointer xx_v(:)
8320        ....
8321        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8322        a = xx_v(3)
8323        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8324 .ve
8325 
8326     Level: advanced
8327 
8328 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8329 M*/
8330 
8331 /*@
8332   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8333   as the original matrix.
8334 
8335   Collective
8336 
8337   Input Parameters:
8338 + mat   - the original matrix
8339 . isrow - parallel `IS` containing the rows this processor should obtain
8340 . 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.
8341 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8342 
8343   Output Parameter:
8344 . newmat - the new submatrix, of the same type as the original matrix
8345 
8346   Level: advanced
8347 
8348   Notes:
8349   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8350 
8351   Some matrix types place restrictions on the row and column indices, such
8352   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;
8353   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8354 
8355   The index sets may not have duplicate entries.
8356 
8357   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8358   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8359   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8360   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8361   you are finished using it.
8362 
8363   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8364   the input matrix.
8365 
8366   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8367 
8368   Example usage:
8369   Consider the following 8x8 matrix with 34 non-zero values, that is
8370   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8371   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8372   as follows
8373 .vb
8374             1  2  0  |  0  3  0  |  0  4
8375     Proc0   0  5  6  |  7  0  0  |  8  0
8376             9  0 10  | 11  0  0  | 12  0
8377     -------------------------------------
8378            13  0 14  | 15 16 17  |  0  0
8379     Proc1   0 18  0  | 19 20 21  |  0  0
8380             0  0  0  | 22 23  0  | 24  0
8381     -------------------------------------
8382     Proc2  25 26 27  |  0  0 28  | 29  0
8383            30  0  0  | 31 32 33  |  0 34
8384 .ve
8385 
8386   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8387 
8388 .vb
8389             2  0  |  0  3  0  |  0
8390     Proc0   5  6  |  7  0  0  |  8
8391     -------------------------------
8392     Proc1  18  0  | 19 20 21  |  0
8393     -------------------------------
8394     Proc2  26 27  |  0  0 28  | 29
8395             0  0  | 31 32 33  |  0
8396 .ve
8397 
8398 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8399 @*/
8400 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8401 {
8402   PetscMPIInt size;
8403   Mat        *local;
8404   IS          iscoltmp;
8405   PetscBool   flg;
8406 
8407   PetscFunctionBegin;
8408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8409   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8410   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8411   PetscAssertPointer(newmat, 5);
8412   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8413   PetscValidType(mat, 1);
8414   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8415   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8416 
8417   MatCheckPreallocated(mat, 1);
8418   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8419 
8420   if (!iscol || isrow == iscol) {
8421     PetscBool   stride;
8422     PetscMPIInt grabentirematrix = 0, grab;
8423     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8424     if (stride) {
8425       PetscInt first, step, n, rstart, rend;
8426       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8427       if (step == 1) {
8428         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8429         if (rstart == first) {
8430           PetscCall(ISGetLocalSize(isrow, &n));
8431           if (n == rend - rstart) grabentirematrix = 1;
8432         }
8433       }
8434     }
8435     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8436     if (grab) {
8437       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8438       if (cll == MAT_INITIAL_MATRIX) {
8439         *newmat = mat;
8440         PetscCall(PetscObjectReference((PetscObject)mat));
8441       }
8442       PetscFunctionReturn(PETSC_SUCCESS);
8443     }
8444   }
8445 
8446   if (!iscol) {
8447     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8448   } else {
8449     iscoltmp = iscol;
8450   }
8451 
8452   /* if original matrix is on just one processor then use submatrix generated */
8453   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8454     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8455     goto setproperties;
8456   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8457     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8458     *newmat = *local;
8459     PetscCall(PetscFree(local));
8460     goto setproperties;
8461   } else if (!mat->ops->createsubmatrix) {
8462     /* Create a new matrix type that implements the operation using the full matrix */
8463     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8464     switch (cll) {
8465     case MAT_INITIAL_MATRIX:
8466       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8467       break;
8468     case MAT_REUSE_MATRIX:
8469       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8470       break;
8471     default:
8472       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8473     }
8474     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8475     goto setproperties;
8476   }
8477 
8478   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8479   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8480   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8481 
8482 setproperties:
8483   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8484   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8485   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8486   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8487   PetscFunctionReturn(PETSC_SUCCESS);
8488 }
8489 
8490 /*@
8491   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8492 
8493   Not Collective
8494 
8495   Input Parameters:
8496 + A - the matrix we wish to propagate options from
8497 - B - the matrix we wish to propagate options to
8498 
8499   Level: beginner
8500 
8501   Note:
8502   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8503 
8504 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8505 @*/
8506 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8507 {
8508   PetscFunctionBegin;
8509   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8510   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8511   B->symmetry_eternal            = A->symmetry_eternal;
8512   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8513   B->symmetric                   = A->symmetric;
8514   B->structurally_symmetric      = A->structurally_symmetric;
8515   B->spd                         = A->spd;
8516   B->hermitian                   = A->hermitian;
8517   PetscFunctionReturn(PETSC_SUCCESS);
8518 }
8519 
8520 /*@
8521   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8522   used during the assembly process to store values that belong to
8523   other processors.
8524 
8525   Not Collective
8526 
8527   Input Parameters:
8528 + mat   - the matrix
8529 . size  - the initial size of the stash.
8530 - bsize - the initial size of the block-stash(if used).
8531 
8532   Options Database Keys:
8533 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8534 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8535 
8536   Level: intermediate
8537 
8538   Notes:
8539   The block-stash is used for values set with `MatSetValuesBlocked()` while
8540   the stash is used for values set with `MatSetValues()`
8541 
8542   Run with the option -info and look for output of the form
8543   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8544   to determine the appropriate value, MM, to use for size and
8545   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8546   to determine the value, BMM to use for bsize
8547 
8548 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8549 @*/
8550 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8551 {
8552   PetscFunctionBegin;
8553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8554   PetscValidType(mat, 1);
8555   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8556   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8557   PetscFunctionReturn(PETSC_SUCCESS);
8558 }
8559 
8560 /*@
8561   MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8562   the matrix
8563 
8564   Neighbor-wise Collective
8565 
8566   Input Parameters:
8567 + A - the matrix
8568 . x - the vector to be multiplied by the interpolation operator
8569 - y - the vector to be added to the result
8570 
8571   Output Parameter:
8572 . w - the resulting vector
8573 
8574   Level: intermediate
8575 
8576   Notes:
8577   `w` may be the same vector as `y`.
8578 
8579   This allows one to use either the restriction or interpolation (its transpose)
8580   matrix to do the interpolation
8581 
8582 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8583 @*/
8584 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8585 {
8586   PetscInt M, N, Ny;
8587 
8588   PetscFunctionBegin;
8589   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8590   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8591   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8592   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8593   PetscCall(MatGetSize(A, &M, &N));
8594   PetscCall(VecGetSize(y, &Ny));
8595   if (M == Ny) {
8596     PetscCall(MatMultAdd(A, x, y, w));
8597   } else {
8598     PetscCall(MatMultTransposeAdd(A, x, y, w));
8599   }
8600   PetscFunctionReturn(PETSC_SUCCESS);
8601 }
8602 
8603 /*@
8604   MatInterpolate - y = A*x or A'*x depending on the shape of
8605   the matrix
8606 
8607   Neighbor-wise Collective
8608 
8609   Input Parameters:
8610 + A - the matrix
8611 - x - the vector to be interpolated
8612 
8613   Output Parameter:
8614 . y - the resulting vector
8615 
8616   Level: intermediate
8617 
8618   Note:
8619   This allows one to use either the restriction or interpolation (its transpose)
8620   matrix to do the interpolation
8621 
8622 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8623 @*/
8624 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8625 {
8626   PetscInt M, N, Ny;
8627 
8628   PetscFunctionBegin;
8629   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8630   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8631   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8632   PetscCall(MatGetSize(A, &M, &N));
8633   PetscCall(VecGetSize(y, &Ny));
8634   if (M == Ny) {
8635     PetscCall(MatMult(A, x, y));
8636   } else {
8637     PetscCall(MatMultTranspose(A, x, y));
8638   }
8639   PetscFunctionReturn(PETSC_SUCCESS);
8640 }
8641 
8642 /*@
8643   MatRestrict - y = A*x or A'*x
8644 
8645   Neighbor-wise Collective
8646 
8647   Input Parameters:
8648 + A - the matrix
8649 - x - the vector to be restricted
8650 
8651   Output Parameter:
8652 . y - the resulting vector
8653 
8654   Level: intermediate
8655 
8656   Note:
8657   This allows one to use either the restriction or interpolation (its transpose)
8658   matrix to do the restriction
8659 
8660 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8661 @*/
8662 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8663 {
8664   PetscInt M, N, Ny;
8665 
8666   PetscFunctionBegin;
8667   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8668   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8669   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8670   PetscCall(MatGetSize(A, &M, &N));
8671   PetscCall(VecGetSize(y, &Ny));
8672   if (M == Ny) {
8673     PetscCall(MatMult(A, x, y));
8674   } else {
8675     PetscCall(MatMultTranspose(A, x, y));
8676   }
8677   PetscFunctionReturn(PETSC_SUCCESS);
8678 }
8679 
8680 /*@
8681   MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8682 
8683   Neighbor-wise Collective
8684 
8685   Input Parameters:
8686 + A - the matrix
8687 . x - the input dense matrix to be multiplied
8688 - w - the input dense matrix to be added to the result
8689 
8690   Output Parameter:
8691 . y - the output dense matrix
8692 
8693   Level: intermediate
8694 
8695   Note:
8696   This allows one to use either the restriction or interpolation (its transpose)
8697   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8698   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8699 
8700 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8701 @*/
8702 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8703 {
8704   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8705   PetscBool trans = PETSC_TRUE;
8706   MatReuse  reuse = MAT_INITIAL_MATRIX;
8707 
8708   PetscFunctionBegin;
8709   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8710   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8711   PetscValidType(x, 2);
8712   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8713   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8714   PetscCall(MatGetSize(A, &M, &N));
8715   PetscCall(MatGetSize(x, &Mx, &Nx));
8716   if (N == Mx) trans = PETSC_FALSE;
8717   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);
8718   Mo = trans ? N : M;
8719   if (*y) {
8720     PetscCall(MatGetSize(*y, &My, &Ny));
8721     if (Mo == My && Nx == Ny) {
8722       reuse = MAT_REUSE_MATRIX;
8723     } else {
8724       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);
8725       PetscCall(MatDestroy(y));
8726     }
8727   }
8728 
8729   if (w && *y == w) { /* this is to minimize changes in PCMG */
8730     PetscBool flg;
8731 
8732     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8733     if (w) {
8734       PetscInt My, Ny, Mw, Nw;
8735 
8736       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8737       PetscCall(MatGetSize(*y, &My, &Ny));
8738       PetscCall(MatGetSize(w, &Mw, &Nw));
8739       if (!flg || My != Mw || Ny != Nw) w = NULL;
8740     }
8741     if (!w) {
8742       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8743       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8744       PetscCall(PetscObjectDereference((PetscObject)w));
8745     } else {
8746       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8747     }
8748   }
8749   if (!trans) {
8750     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8751   } else {
8752     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8753   }
8754   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8755   PetscFunctionReturn(PETSC_SUCCESS);
8756 }
8757 
8758 /*@
8759   MatMatInterpolate - Y = A*X or A'*X
8760 
8761   Neighbor-wise Collective
8762 
8763   Input Parameters:
8764 + A - the matrix
8765 - x - the input dense matrix
8766 
8767   Output Parameter:
8768 . y - the output dense matrix
8769 
8770   Level: intermediate
8771 
8772   Note:
8773   This allows one to use either the restriction or interpolation (its transpose)
8774   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8775   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8776 
8777 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8778 @*/
8779 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8780 {
8781   PetscFunctionBegin;
8782   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8783   PetscFunctionReturn(PETSC_SUCCESS);
8784 }
8785 
8786 /*@
8787   MatMatRestrict - Y = A*X or A'*X
8788 
8789   Neighbor-wise Collective
8790 
8791   Input Parameters:
8792 + A - the matrix
8793 - x - the input dense matrix
8794 
8795   Output Parameter:
8796 . y - the output dense matrix
8797 
8798   Level: intermediate
8799 
8800   Note:
8801   This allows one to use either the restriction or interpolation (its transpose)
8802   matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8803   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8804 
8805 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8806 @*/
8807 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8808 {
8809   PetscFunctionBegin;
8810   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8811   PetscFunctionReturn(PETSC_SUCCESS);
8812 }
8813 
8814 /*@
8815   MatGetNullSpace - retrieves the null space of a matrix.
8816 
8817   Logically Collective
8818 
8819   Input Parameters:
8820 + mat    - the matrix
8821 - nullsp - the null space object
8822 
8823   Level: developer
8824 
8825 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8826 @*/
8827 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8828 {
8829   PetscFunctionBegin;
8830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8831   PetscAssertPointer(nullsp, 2);
8832   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8833   PetscFunctionReturn(PETSC_SUCCESS);
8834 }
8835 
8836 /*@
8837   MatSetNullSpace - attaches a null space to a matrix.
8838 
8839   Logically Collective
8840 
8841   Input Parameters:
8842 + mat    - the matrix
8843 - nullsp - the null space object
8844 
8845   Level: advanced
8846 
8847   Notes:
8848   This null space is used by the `KSP` linear solvers to solve singular systems.
8849 
8850   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`
8851 
8852   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
8853   to zero but the linear system will still be solved in a least squares sense.
8854 
8855   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8856   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).
8857   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
8858   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
8859   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).
8860   This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8861 
8862   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8863   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8864   routine also automatically calls `MatSetTransposeNullSpace()`.
8865 
8866   The user should call `MatNullSpaceDestroy()`.
8867 
8868 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8869           `KSPSetPCSide()`
8870 @*/
8871 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8872 {
8873   PetscFunctionBegin;
8874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8875   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8876   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8877   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8878   mat->nullsp = nullsp;
8879   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8880   PetscFunctionReturn(PETSC_SUCCESS);
8881 }
8882 
8883 /*@
8884   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8885 
8886   Logically Collective
8887 
8888   Input Parameters:
8889 + mat    - the matrix
8890 - nullsp - the null space object
8891 
8892   Level: developer
8893 
8894 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8895 @*/
8896 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8897 {
8898   PetscFunctionBegin;
8899   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8900   PetscValidType(mat, 1);
8901   PetscAssertPointer(nullsp, 2);
8902   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8903   PetscFunctionReturn(PETSC_SUCCESS);
8904 }
8905 
8906 /*@
8907   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8908 
8909   Logically Collective
8910 
8911   Input Parameters:
8912 + mat    - the matrix
8913 - nullsp - the null space object
8914 
8915   Level: advanced
8916 
8917   Notes:
8918   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8919 
8920   See `MatSetNullSpace()`
8921 
8922 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8923 @*/
8924 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8925 {
8926   PetscFunctionBegin;
8927   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8928   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8929   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8930   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8931   mat->transnullsp = nullsp;
8932   PetscFunctionReturn(PETSC_SUCCESS);
8933 }
8934 
8935 /*@
8936   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8937   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8938 
8939   Logically Collective
8940 
8941   Input Parameters:
8942 + mat    - the matrix
8943 - nullsp - the null space object
8944 
8945   Level: advanced
8946 
8947   Notes:
8948   Overwrites any previous near null space that may have been attached
8949 
8950   You can remove the null space by calling this routine with an nullsp of `NULL`
8951 
8952 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8953 @*/
8954 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8955 {
8956   PetscFunctionBegin;
8957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8958   PetscValidType(mat, 1);
8959   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8960   MatCheckPreallocated(mat, 1);
8961   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8962   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8963   mat->nearnullsp = nullsp;
8964   PetscFunctionReturn(PETSC_SUCCESS);
8965 }
8966 
8967 /*@
8968   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8969 
8970   Not Collective
8971 
8972   Input Parameter:
8973 . mat - the matrix
8974 
8975   Output Parameter:
8976 . nullsp - the null space object, `NULL` if not set
8977 
8978   Level: advanced
8979 
8980 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8981 @*/
8982 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8983 {
8984   PetscFunctionBegin;
8985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8986   PetscValidType(mat, 1);
8987   PetscAssertPointer(nullsp, 2);
8988   MatCheckPreallocated(mat, 1);
8989   *nullsp = mat->nearnullsp;
8990   PetscFunctionReturn(PETSC_SUCCESS);
8991 }
8992 
8993 /*@C
8994   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8995 
8996   Collective
8997 
8998   Input Parameters:
8999 + mat  - the matrix
9000 . row  - row/column permutation
9001 - info - information on desired factorization process
9002 
9003   Level: developer
9004 
9005   Notes:
9006   Probably really in-place only when level of fill is zero, otherwise allocates
9007   new space to store factored matrix and deletes previous memory.
9008 
9009   Most users should employ the `KSP` interface for linear solvers
9010   instead of working directly with matrix algebra routines such as this.
9011   See, e.g., `KSPCreate()`.
9012 
9013   Developer Notes:
9014   The Fortran interface is not autogenerated as the
9015   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9016 
9017 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9018 @*/
9019 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9020 {
9021   PetscFunctionBegin;
9022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9023   PetscValidType(mat, 1);
9024   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9025   PetscAssertPointer(info, 3);
9026   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9027   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9028   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9029   MatCheckPreallocated(mat, 1);
9030   PetscUseTypeMethod(mat, iccfactor, row, info);
9031   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9032   PetscFunctionReturn(PETSC_SUCCESS);
9033 }
9034 
9035 /*@
9036   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9037   ghosted ones.
9038 
9039   Not Collective
9040 
9041   Input Parameters:
9042 + mat  - the matrix
9043 - diag - the diagonal values, including ghost ones
9044 
9045   Level: developer
9046 
9047   Notes:
9048   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9049 
9050   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9051 
9052 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9053 @*/
9054 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9055 {
9056   PetscMPIInt size;
9057 
9058   PetscFunctionBegin;
9059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9060   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9061   PetscValidType(mat, 1);
9062 
9063   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9064   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9065   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9066   if (size == 1) {
9067     PetscInt n, m;
9068     PetscCall(VecGetSize(diag, &n));
9069     PetscCall(MatGetSize(mat, NULL, &m));
9070     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9071     PetscCall(MatDiagonalScale(mat, NULL, diag));
9072   } else {
9073     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9074   }
9075   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9076   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9077   PetscFunctionReturn(PETSC_SUCCESS);
9078 }
9079 
9080 /*@
9081   MatGetInertia - Gets the inertia from a factored matrix
9082 
9083   Collective
9084 
9085   Input Parameter:
9086 . mat - the matrix
9087 
9088   Output Parameters:
9089 + nneg  - number of negative eigenvalues
9090 . nzero - number of zero eigenvalues
9091 - npos  - number of positive eigenvalues
9092 
9093   Level: advanced
9094 
9095   Note:
9096   Matrix must have been factored by `MatCholeskyFactor()`
9097 
9098 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9099 @*/
9100 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9101 {
9102   PetscFunctionBegin;
9103   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9104   PetscValidType(mat, 1);
9105   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9106   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9107   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9108   PetscFunctionReturn(PETSC_SUCCESS);
9109 }
9110 
9111 /*@C
9112   MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9113 
9114   Neighbor-wise Collective
9115 
9116   Input Parameters:
9117 + mat - the factored matrix obtained with `MatGetFactor()`
9118 - b   - the right-hand-side vectors
9119 
9120   Output Parameter:
9121 . x - the result vectors
9122 
9123   Level: developer
9124 
9125   Note:
9126   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9127   call `MatSolves`(A,x,x).
9128 
9129 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9130 @*/
9131 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9132 {
9133   PetscFunctionBegin;
9134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9135   PetscValidType(mat, 1);
9136   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9137   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9138   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9139 
9140   MatCheckPreallocated(mat, 1);
9141   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9142   PetscUseTypeMethod(mat, solves, b, x);
9143   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9144   PetscFunctionReturn(PETSC_SUCCESS);
9145 }
9146 
9147 /*@
9148   MatIsSymmetric - Test whether a matrix is symmetric
9149 
9150   Collective
9151 
9152   Input Parameters:
9153 + A   - the matrix to test
9154 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9155 
9156   Output Parameter:
9157 . flg - the result
9158 
9159   Level: intermediate
9160 
9161   Notes:
9162   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9163 
9164   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9165 
9166   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9167   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9168 
9169 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9170           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9171 @*/
9172 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9173 {
9174   PetscFunctionBegin;
9175   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9176   PetscAssertPointer(flg, 3);
9177 
9178   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9179   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9180   else {
9181     PetscUseTypeMethod(A, issymmetric, tol, flg);
9182     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9183   }
9184   PetscFunctionReturn(PETSC_SUCCESS);
9185 }
9186 
9187 /*@
9188   MatIsHermitian - Test whether a matrix is Hermitian
9189 
9190   Collective
9191 
9192   Input Parameters:
9193 + A   - the matrix to test
9194 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9195 
9196   Output Parameter:
9197 . flg - the result
9198 
9199   Level: intermediate
9200 
9201   Notes:
9202   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9203 
9204   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9205 
9206   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9207   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9208 
9209 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9210           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9211 @*/
9212 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9213 {
9214   PetscFunctionBegin;
9215   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9216   PetscAssertPointer(flg, 3);
9217 
9218   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9219   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9220   else {
9221     PetscUseTypeMethod(A, ishermitian, tol, flg);
9222     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9223   }
9224   PetscFunctionReturn(PETSC_SUCCESS);
9225 }
9226 
9227 /*@
9228   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9229 
9230   Not Collective
9231 
9232   Input Parameter:
9233 . A - the matrix to check
9234 
9235   Output Parameters:
9236 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9237 - flg - the result (only valid if set is `PETSC_TRUE`)
9238 
9239   Level: advanced
9240 
9241   Notes:
9242   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9243   if you want it explicitly checked
9244 
9245   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9246   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9247 
9248 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9249 @*/
9250 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9251 {
9252   PetscFunctionBegin;
9253   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9254   PetscAssertPointer(set, 2);
9255   PetscAssertPointer(flg, 3);
9256   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9257     *set = PETSC_TRUE;
9258     *flg = PetscBool3ToBool(A->symmetric);
9259   } else {
9260     *set = PETSC_FALSE;
9261   }
9262   PetscFunctionReturn(PETSC_SUCCESS);
9263 }
9264 
9265 /*@
9266   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9267 
9268   Not Collective
9269 
9270   Input Parameter:
9271 . A - the matrix to check
9272 
9273   Output Parameters:
9274 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9275 - flg - the result (only valid if set is `PETSC_TRUE`)
9276 
9277   Level: advanced
9278 
9279   Notes:
9280   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9281 
9282   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9283   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9284 
9285 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9286 @*/
9287 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9288 {
9289   PetscFunctionBegin;
9290   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9291   PetscAssertPointer(set, 2);
9292   PetscAssertPointer(flg, 3);
9293   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9294     *set = PETSC_TRUE;
9295     *flg = PetscBool3ToBool(A->spd);
9296   } else {
9297     *set = PETSC_FALSE;
9298   }
9299   PetscFunctionReturn(PETSC_SUCCESS);
9300 }
9301 
9302 /*@
9303   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9304 
9305   Not Collective
9306 
9307   Input Parameter:
9308 . A - the matrix to check
9309 
9310   Output Parameters:
9311 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9312 - flg - the result (only valid if set is `PETSC_TRUE`)
9313 
9314   Level: advanced
9315 
9316   Notes:
9317   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9318   if you want it explicitly checked
9319 
9320   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9321   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9322 
9323 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9324 @*/
9325 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9326 {
9327   PetscFunctionBegin;
9328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9329   PetscAssertPointer(set, 2);
9330   PetscAssertPointer(flg, 3);
9331   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9332     *set = PETSC_TRUE;
9333     *flg = PetscBool3ToBool(A->hermitian);
9334   } else {
9335     *set = PETSC_FALSE;
9336   }
9337   PetscFunctionReturn(PETSC_SUCCESS);
9338 }
9339 
9340 /*@
9341   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9342 
9343   Collective
9344 
9345   Input Parameter:
9346 . A - the matrix to test
9347 
9348   Output Parameter:
9349 . flg - the result
9350 
9351   Level: intermediate
9352 
9353   Notes:
9354   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9355 
9356   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
9357   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9358 
9359 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9360 @*/
9361 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9362 {
9363   PetscFunctionBegin;
9364   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9365   PetscAssertPointer(flg, 2);
9366   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9367     *flg = PetscBool3ToBool(A->structurally_symmetric);
9368   } else {
9369     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9370     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9371   }
9372   PetscFunctionReturn(PETSC_SUCCESS);
9373 }
9374 
9375 /*@
9376   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9377 
9378   Not Collective
9379 
9380   Input Parameter:
9381 . A - the matrix to check
9382 
9383   Output Parameters:
9384 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9385 - flg - the result (only valid if set is PETSC_TRUE)
9386 
9387   Level: advanced
9388 
9389   Notes:
9390   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
9391   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9392 
9393   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9394 
9395 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9396 @*/
9397 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9398 {
9399   PetscFunctionBegin;
9400   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9401   PetscAssertPointer(set, 2);
9402   PetscAssertPointer(flg, 3);
9403   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9404     *set = PETSC_TRUE;
9405     *flg = PetscBool3ToBool(A->structurally_symmetric);
9406   } else {
9407     *set = PETSC_FALSE;
9408   }
9409   PetscFunctionReturn(PETSC_SUCCESS);
9410 }
9411 
9412 /*@
9413   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9414   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9415 
9416   Not Collective
9417 
9418   Input Parameter:
9419 . mat - the matrix
9420 
9421   Output Parameters:
9422 + nstash    - the size of the stash
9423 . reallocs  - the number of additional mallocs incurred.
9424 . bnstash   - the size of the block stash
9425 - breallocs - the number of additional mallocs incurred.in the block stash
9426 
9427   Level: advanced
9428 
9429 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9430 @*/
9431 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9432 {
9433   PetscFunctionBegin;
9434   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9435   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9436   PetscFunctionReturn(PETSC_SUCCESS);
9437 }
9438 
9439 /*@C
9440   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9441   parallel layout, `PetscLayout` for rows and columns
9442 
9443   Collective
9444 
9445   Input Parameter:
9446 . mat - the matrix
9447 
9448   Output Parameters:
9449 + right - (optional) vector that the matrix can be multiplied against
9450 - left  - (optional) vector that the matrix vector product can be stored in
9451 
9452   Level: advanced
9453 
9454   Notes:
9455   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()`.
9456 
9457   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9458 
9459 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9460 @*/
9461 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9462 {
9463   PetscFunctionBegin;
9464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9465   PetscValidType(mat, 1);
9466   if (mat->ops->getvecs) {
9467     PetscUseTypeMethod(mat, getvecs, right, left);
9468   } else {
9469     if (right) {
9470       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9471       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9472       PetscCall(VecSetType(*right, mat->defaultvectype));
9473 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9474       if (mat->boundtocpu && mat->bindingpropagates) {
9475         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9476         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9477       }
9478 #endif
9479     }
9480     if (left) {
9481       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9482       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9483       PetscCall(VecSetType(*left, mat->defaultvectype));
9484 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9485       if (mat->boundtocpu && mat->bindingpropagates) {
9486         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9487         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9488       }
9489 #endif
9490     }
9491   }
9492   PetscFunctionReturn(PETSC_SUCCESS);
9493 }
9494 
9495 /*@C
9496   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9497   with default values.
9498 
9499   Not Collective
9500 
9501   Input Parameter:
9502 . info - the `MatFactorInfo` data structure
9503 
9504   Level: developer
9505 
9506   Notes:
9507   The solvers are generally used through the `KSP` and `PC` objects, for example
9508   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9509 
9510   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9511 
9512   Developer Notes:
9513   The Fortran interface is not autogenerated as the
9514   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9515 
9516 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9517 @*/
9518 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9519 {
9520   PetscFunctionBegin;
9521   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9522   PetscFunctionReturn(PETSC_SUCCESS);
9523 }
9524 
9525 /*@
9526   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9527 
9528   Collective
9529 
9530   Input Parameters:
9531 + mat - the factored matrix
9532 - is  - the index set defining the Schur indices (0-based)
9533 
9534   Level: advanced
9535 
9536   Notes:
9537   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9538 
9539   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9540 
9541   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9542 
9543 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9544           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9545 @*/
9546 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9547 {
9548   PetscErrorCode (*f)(Mat, IS);
9549 
9550   PetscFunctionBegin;
9551   PetscValidType(mat, 1);
9552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9553   PetscValidType(is, 2);
9554   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9555   PetscCheckSameComm(mat, 1, is, 2);
9556   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9557   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9558   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9559   PetscCall(MatDestroy(&mat->schur));
9560   PetscCall((*f)(mat, is));
9561   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9562   PetscFunctionReturn(PETSC_SUCCESS);
9563 }
9564 
9565 /*@
9566   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9567 
9568   Logically Collective
9569 
9570   Input Parameters:
9571 + F      - the factored matrix obtained by calling `MatGetFactor()`
9572 . S      - location where to return the Schur complement, can be `NULL`
9573 - status - the status of the Schur complement matrix, can be `NULL`
9574 
9575   Level: advanced
9576 
9577   Notes:
9578   You must call `MatFactorSetSchurIS()` before calling this routine.
9579 
9580   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9581 
9582   The routine provides a copy of the Schur matrix stored within the solver data structures.
9583   The caller must destroy the object when it is no longer needed.
9584   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9585 
9586   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)
9587 
9588   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9589 
9590   Developer Notes:
9591   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9592   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9593 
9594 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9595 @*/
9596 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9597 {
9598   PetscFunctionBegin;
9599   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9600   if (S) PetscAssertPointer(S, 2);
9601   if (status) PetscAssertPointer(status, 3);
9602   if (S) {
9603     PetscErrorCode (*f)(Mat, Mat *);
9604 
9605     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9606     if (f) {
9607       PetscCall((*f)(F, S));
9608     } else {
9609       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9610     }
9611   }
9612   if (status) *status = F->schur_status;
9613   PetscFunctionReturn(PETSC_SUCCESS);
9614 }
9615 
9616 /*@
9617   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9618 
9619   Logically Collective
9620 
9621   Input Parameters:
9622 + F      - the factored matrix obtained by calling `MatGetFactor()`
9623 . S      - location where to return the Schur complement, can be `NULL`
9624 - status - the status of the Schur complement matrix, can be `NULL`
9625 
9626   Level: advanced
9627 
9628   Notes:
9629   You must call `MatFactorSetSchurIS()` before calling this routine.
9630 
9631   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9632 
9633   The routine returns a the Schur Complement stored within the data structures of the solver.
9634 
9635   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9636 
9637   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9638 
9639   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9640 
9641   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9642 
9643 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9644 @*/
9645 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9646 {
9647   PetscFunctionBegin;
9648   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9649   if (S) {
9650     PetscAssertPointer(S, 2);
9651     *S = F->schur;
9652   }
9653   if (status) {
9654     PetscAssertPointer(status, 3);
9655     *status = F->schur_status;
9656   }
9657   PetscFunctionReturn(PETSC_SUCCESS);
9658 }
9659 
9660 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9661 {
9662   Mat S = F->schur;
9663 
9664   PetscFunctionBegin;
9665   switch (F->schur_status) {
9666   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9667   case MAT_FACTOR_SCHUR_INVERTED:
9668     if (S) {
9669       S->ops->solve             = NULL;
9670       S->ops->matsolve          = NULL;
9671       S->ops->solvetranspose    = NULL;
9672       S->ops->matsolvetranspose = NULL;
9673       S->ops->solveadd          = NULL;
9674       S->ops->solvetransposeadd = NULL;
9675       S->factortype             = MAT_FACTOR_NONE;
9676       PetscCall(PetscFree(S->solvertype));
9677     }
9678   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9679     break;
9680   default:
9681     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9682   }
9683   PetscFunctionReturn(PETSC_SUCCESS);
9684 }
9685 
9686 /*@
9687   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9688 
9689   Logically Collective
9690 
9691   Input Parameters:
9692 + F      - the factored matrix obtained by calling `MatGetFactor()`
9693 . S      - location where the Schur complement is stored
9694 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9695 
9696   Level: advanced
9697 
9698 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9699 @*/
9700 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9701 {
9702   PetscFunctionBegin;
9703   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9704   if (S) {
9705     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9706     *S = NULL;
9707   }
9708   F->schur_status = status;
9709   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9710   PetscFunctionReturn(PETSC_SUCCESS);
9711 }
9712 
9713 /*@
9714   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9715 
9716   Logically Collective
9717 
9718   Input Parameters:
9719 + F   - the factored matrix obtained by calling `MatGetFactor()`
9720 . rhs - location where the right hand side of the Schur complement system is stored
9721 - sol - location where the solution of the Schur complement system has to be returned
9722 
9723   Level: advanced
9724 
9725   Notes:
9726   The sizes of the vectors should match the size of the Schur complement
9727 
9728   Must be called after `MatFactorSetSchurIS()`
9729 
9730 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9731 @*/
9732 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9733 {
9734   PetscFunctionBegin;
9735   PetscValidType(F, 1);
9736   PetscValidType(rhs, 2);
9737   PetscValidType(sol, 3);
9738   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9739   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9740   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9741   PetscCheckSameComm(F, 1, rhs, 2);
9742   PetscCheckSameComm(F, 1, sol, 3);
9743   PetscCall(MatFactorFactorizeSchurComplement(F));
9744   switch (F->schur_status) {
9745   case MAT_FACTOR_SCHUR_FACTORED:
9746     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9747     break;
9748   case MAT_FACTOR_SCHUR_INVERTED:
9749     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9750     break;
9751   default:
9752     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9753   }
9754   PetscFunctionReturn(PETSC_SUCCESS);
9755 }
9756 
9757 /*@
9758   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9759 
9760   Logically Collective
9761 
9762   Input Parameters:
9763 + F   - the factored matrix obtained by calling `MatGetFactor()`
9764 . rhs - location where the right hand side of the Schur complement system is stored
9765 - sol - location where the solution of the Schur complement system has to be returned
9766 
9767   Level: advanced
9768 
9769   Notes:
9770   The sizes of the vectors should match the size of the Schur complement
9771 
9772   Must be called after `MatFactorSetSchurIS()`
9773 
9774 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9775 @*/
9776 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9777 {
9778   PetscFunctionBegin;
9779   PetscValidType(F, 1);
9780   PetscValidType(rhs, 2);
9781   PetscValidType(sol, 3);
9782   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9783   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9784   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9785   PetscCheckSameComm(F, 1, rhs, 2);
9786   PetscCheckSameComm(F, 1, sol, 3);
9787   PetscCall(MatFactorFactorizeSchurComplement(F));
9788   switch (F->schur_status) {
9789   case MAT_FACTOR_SCHUR_FACTORED:
9790     PetscCall(MatSolve(F->schur, rhs, sol));
9791     break;
9792   case MAT_FACTOR_SCHUR_INVERTED:
9793     PetscCall(MatMult(F->schur, rhs, sol));
9794     break;
9795   default:
9796     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9797   }
9798   PetscFunctionReturn(PETSC_SUCCESS);
9799 }
9800 
9801 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9802 #if PetscDefined(HAVE_CUDA)
9803 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9804 #endif
9805 
9806 /* Schur status updated in the interface */
9807 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9808 {
9809   Mat S = F->schur;
9810 
9811   PetscFunctionBegin;
9812   if (S) {
9813     PetscMPIInt size;
9814     PetscBool   isdense, isdensecuda;
9815 
9816     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9817     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9818     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9819     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9820     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9821     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9822     if (isdense) {
9823       PetscCall(MatSeqDenseInvertFactors_Private(S));
9824     } else if (isdensecuda) {
9825 #if defined(PETSC_HAVE_CUDA)
9826       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9827 #endif
9828     }
9829     // HIP??????????????
9830     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9831   }
9832   PetscFunctionReturn(PETSC_SUCCESS);
9833 }
9834 
9835 /*@
9836   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9837 
9838   Logically Collective
9839 
9840   Input Parameter:
9841 . F - the factored matrix obtained by calling `MatGetFactor()`
9842 
9843   Level: advanced
9844 
9845   Notes:
9846   Must be called after `MatFactorSetSchurIS()`.
9847 
9848   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9849 
9850 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9851 @*/
9852 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9853 {
9854   PetscFunctionBegin;
9855   PetscValidType(F, 1);
9856   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9857   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9858   PetscCall(MatFactorFactorizeSchurComplement(F));
9859   PetscCall(MatFactorInvertSchurComplement_Private(F));
9860   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9861   PetscFunctionReturn(PETSC_SUCCESS);
9862 }
9863 
9864 /*@
9865   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9866 
9867   Logically Collective
9868 
9869   Input Parameter:
9870 . F - the factored matrix obtained by calling `MatGetFactor()`
9871 
9872   Level: advanced
9873 
9874   Note:
9875   Must be called after `MatFactorSetSchurIS()`
9876 
9877 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9878 @*/
9879 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9880 {
9881   MatFactorInfo info;
9882 
9883   PetscFunctionBegin;
9884   PetscValidType(F, 1);
9885   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9886   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9887   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9888   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9889   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9890     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9891   } else {
9892     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9893   }
9894   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9895   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9896   PetscFunctionReturn(PETSC_SUCCESS);
9897 }
9898 
9899 /*@
9900   MatPtAP - Creates the matrix product C = P^T * A * P
9901 
9902   Neighbor-wise Collective
9903 
9904   Input Parameters:
9905 + A     - the matrix
9906 . P     - the projection matrix
9907 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9908 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9909           if the result is a dense matrix this is irrelevant
9910 
9911   Output Parameter:
9912 . C - the product matrix
9913 
9914   Level: intermediate
9915 
9916   Notes:
9917   C will be created and must be destroyed by the user with `MatDestroy()`.
9918 
9919   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9920 
9921   Developer Notes:
9922   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9923 
9924 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9925 @*/
9926 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9927 {
9928   PetscFunctionBegin;
9929   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9930   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9931 
9932   if (scall == MAT_INITIAL_MATRIX) {
9933     PetscCall(MatProductCreate(A, P, NULL, C));
9934     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9935     PetscCall(MatProductSetAlgorithm(*C, "default"));
9936     PetscCall(MatProductSetFill(*C, fill));
9937 
9938     (*C)->product->api_user = PETSC_TRUE;
9939     PetscCall(MatProductSetFromOptions(*C));
9940     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);
9941     PetscCall(MatProductSymbolic(*C));
9942   } else { /* scall == MAT_REUSE_MATRIX */
9943     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9944   }
9945 
9946   PetscCall(MatProductNumeric(*C));
9947   (*C)->symmetric = A->symmetric;
9948   (*C)->spd       = A->spd;
9949   PetscFunctionReturn(PETSC_SUCCESS);
9950 }
9951 
9952 /*@
9953   MatRARt - Creates the matrix product C = R * A * R^T
9954 
9955   Neighbor-wise Collective
9956 
9957   Input Parameters:
9958 + A     - the matrix
9959 . R     - the projection matrix
9960 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9961 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9962           if the result is a dense matrix this is irrelevant
9963 
9964   Output Parameter:
9965 . C - the product matrix
9966 
9967   Level: intermediate
9968 
9969   Notes:
9970   C will be created and must be destroyed by the user with `MatDestroy()`.
9971 
9972   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9973 
9974   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9975   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9976   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9977   We recommend using MatPtAP().
9978 
9979 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9980 @*/
9981 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9982 {
9983   PetscFunctionBegin;
9984   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9985   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9986 
9987   if (scall == MAT_INITIAL_MATRIX) {
9988     PetscCall(MatProductCreate(A, R, NULL, C));
9989     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9990     PetscCall(MatProductSetAlgorithm(*C, "default"));
9991     PetscCall(MatProductSetFill(*C, fill));
9992 
9993     (*C)->product->api_user = PETSC_TRUE;
9994     PetscCall(MatProductSetFromOptions(*C));
9995     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);
9996     PetscCall(MatProductSymbolic(*C));
9997   } else { /* scall == MAT_REUSE_MATRIX */
9998     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9999   }
10000 
10001   PetscCall(MatProductNumeric(*C));
10002   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10003   PetscFunctionReturn(PETSC_SUCCESS);
10004 }
10005 
10006 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10007 {
10008   PetscFunctionBegin;
10009   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10010 
10011   if (scall == MAT_INITIAL_MATRIX) {
10012     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10013     PetscCall(MatProductCreate(A, B, NULL, C));
10014     PetscCall(MatProductSetType(*C, ptype));
10015     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10016     PetscCall(MatProductSetFill(*C, fill));
10017 
10018     (*C)->product->api_user = PETSC_TRUE;
10019     PetscCall(MatProductSetFromOptions(*C));
10020     PetscCall(MatProductSymbolic(*C));
10021   } else { /* scall == MAT_REUSE_MATRIX */
10022     Mat_Product *product = (*C)->product;
10023     PetscBool    isdense;
10024 
10025     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10026     if (isdense && product && product->type != ptype) {
10027       PetscCall(MatProductClear(*C));
10028       product = NULL;
10029     }
10030     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10031     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10032       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10033       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10034       product           = (*C)->product;
10035       product->fill     = fill;
10036       product->api_user = PETSC_TRUE;
10037       product->clear    = PETSC_TRUE;
10038 
10039       PetscCall(MatProductSetType(*C, ptype));
10040       PetscCall(MatProductSetFromOptions(*C));
10041       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);
10042       PetscCall(MatProductSymbolic(*C));
10043     } else { /* user may change input matrices A or B when REUSE */
10044       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10045     }
10046   }
10047   PetscCall(MatProductNumeric(*C));
10048   PetscFunctionReturn(PETSC_SUCCESS);
10049 }
10050 
10051 /*@
10052   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10053 
10054   Neighbor-wise Collective
10055 
10056   Input Parameters:
10057 + A     - the left matrix
10058 . B     - the right matrix
10059 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10060 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10061           if the result is a dense matrix this is irrelevant
10062 
10063   Output Parameter:
10064 . C - the product matrix
10065 
10066   Notes:
10067   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10068 
10069   `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
10070   call to this function with `MAT_INITIAL_MATRIX`.
10071 
10072   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10073 
10074   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`,
10075   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10076 
10077   Example of Usage:
10078 .vb
10079      MatProductCreate(A,B,NULL,&C);
10080      MatProductSetType(C,MATPRODUCT_AB);
10081      MatProductSymbolic(C);
10082      MatProductNumeric(C); // compute C=A * B
10083      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10084      MatProductNumeric(C);
10085      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10086      MatProductNumeric(C);
10087 .ve
10088 
10089   Level: intermediate
10090 
10091 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10092 @*/
10093 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10094 {
10095   PetscFunctionBegin;
10096   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10097   PetscFunctionReturn(PETSC_SUCCESS);
10098 }
10099 
10100 /*@
10101   MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10102 
10103   Neighbor-wise Collective
10104 
10105   Input Parameters:
10106 + A     - the left matrix
10107 . B     - the right matrix
10108 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10109 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10110 
10111   Output Parameter:
10112 . C - the product matrix
10113 
10114   Level: intermediate
10115 
10116   Notes:
10117   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10118 
10119   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10120 
10121   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10122   actually needed.
10123 
10124   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10125   and for pairs of `MATMPIDENSE` matrices.
10126 
10127   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10128 
10129   Options Database Keys:
10130 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10131               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10132               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10133 
10134 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10135 @*/
10136 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10137 {
10138   PetscFunctionBegin;
10139   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10140   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10141   PetscFunctionReturn(PETSC_SUCCESS);
10142 }
10143 
10144 /*@
10145   MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10146 
10147   Neighbor-wise Collective
10148 
10149   Input Parameters:
10150 + A     - the left matrix
10151 . B     - the right matrix
10152 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10153 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10154 
10155   Output Parameter:
10156 . C - the product matrix
10157 
10158   Level: intermediate
10159 
10160   Notes:
10161   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10162 
10163   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10164 
10165   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10166 
10167   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10168   actually needed.
10169 
10170   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10171   which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10172 
10173 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10174 @*/
10175 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10176 {
10177   PetscFunctionBegin;
10178   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10179   PetscFunctionReturn(PETSC_SUCCESS);
10180 }
10181 
10182 /*@
10183   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10184 
10185   Neighbor-wise Collective
10186 
10187   Input Parameters:
10188 + A     - the left matrix
10189 . B     - the middle matrix
10190 . C     - the right matrix
10191 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10192 - 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
10193           if the result is a dense matrix this is irrelevant
10194 
10195   Output Parameter:
10196 . D - the product matrix
10197 
10198   Level: intermediate
10199 
10200   Notes:
10201   Unless scall is `MAT_REUSE_MATRIX` D will be created.
10202 
10203   `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10204 
10205   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10206 
10207   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10208   actually needed.
10209 
10210   If you have many matrices with the same non-zero structure to multiply, you
10211   should use `MAT_REUSE_MATRIX` in all calls but the first
10212 
10213 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10214 @*/
10215 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10216 {
10217   PetscFunctionBegin;
10218   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10219   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10220 
10221   if (scall == MAT_INITIAL_MATRIX) {
10222     PetscCall(MatProductCreate(A, B, C, D));
10223     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10224     PetscCall(MatProductSetAlgorithm(*D, "default"));
10225     PetscCall(MatProductSetFill(*D, fill));
10226 
10227     (*D)->product->api_user = PETSC_TRUE;
10228     PetscCall(MatProductSetFromOptions(*D));
10229     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,
10230                ((PetscObject)C)->type_name);
10231     PetscCall(MatProductSymbolic(*D));
10232   } else { /* user may change input matrices when REUSE */
10233     PetscCall(MatProductReplaceMats(A, B, C, *D));
10234   }
10235   PetscCall(MatProductNumeric(*D));
10236   PetscFunctionReturn(PETSC_SUCCESS);
10237 }
10238 
10239 /*@
10240   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10241 
10242   Collective
10243 
10244   Input Parameters:
10245 + mat      - the matrix
10246 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10247 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10248 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10249 
10250   Output Parameter:
10251 . matredundant - redundant matrix
10252 
10253   Level: advanced
10254 
10255   Notes:
10256   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10257   original matrix has not changed from that last call to MatCreateRedundantMatrix().
10258 
10259   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10260   calling it.
10261 
10262   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10263 
10264 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10265 @*/
10266 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10267 {
10268   MPI_Comm       comm;
10269   PetscMPIInt    size;
10270   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10271   Mat_Redundant *redund     = NULL;
10272   PetscSubcomm   psubcomm   = NULL;
10273   MPI_Comm       subcomm_in = subcomm;
10274   Mat           *matseq;
10275   IS             isrow, iscol;
10276   PetscBool      newsubcomm = PETSC_FALSE;
10277 
10278   PetscFunctionBegin;
10279   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10280   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10281     PetscAssertPointer(*matredundant, 5);
10282     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10283   }
10284 
10285   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10286   if (size == 1 || nsubcomm == 1) {
10287     if (reuse == MAT_INITIAL_MATRIX) {
10288       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10289     } else {
10290       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");
10291       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10292     }
10293     PetscFunctionReturn(PETSC_SUCCESS);
10294   }
10295 
10296   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10297   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10298   MatCheckPreallocated(mat, 1);
10299 
10300   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10301   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10302     /* create psubcomm, then get subcomm */
10303     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10304     PetscCallMPI(MPI_Comm_size(comm, &size));
10305     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10306 
10307     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10308     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10309     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10310     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10311     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10312     newsubcomm = PETSC_TRUE;
10313     PetscCall(PetscSubcommDestroy(&psubcomm));
10314   }
10315 
10316   /* get isrow, iscol and a local sequential matrix matseq[0] */
10317   if (reuse == MAT_INITIAL_MATRIX) {
10318     mloc_sub = PETSC_DECIDE;
10319     nloc_sub = PETSC_DECIDE;
10320     if (bs < 1) {
10321       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10322       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10323     } else {
10324       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10325       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10326     }
10327     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10328     rstart = rend - mloc_sub;
10329     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10330     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10331     PetscCall(ISSetIdentity(iscol));
10332   } else { /* reuse == MAT_REUSE_MATRIX */
10333     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");
10334     /* retrieve subcomm */
10335     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10336     redund = (*matredundant)->redundant;
10337     isrow  = redund->isrow;
10338     iscol  = redund->iscol;
10339     matseq = redund->matseq;
10340   }
10341   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10342 
10343   /* get matredundant over subcomm */
10344   if (reuse == MAT_INITIAL_MATRIX) {
10345     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10346 
10347     /* create a supporting struct and attach it to C for reuse */
10348     PetscCall(PetscNew(&redund));
10349     (*matredundant)->redundant = redund;
10350     redund->isrow              = isrow;
10351     redund->iscol              = iscol;
10352     redund->matseq             = matseq;
10353     if (newsubcomm) {
10354       redund->subcomm = subcomm;
10355     } else {
10356       redund->subcomm = MPI_COMM_NULL;
10357     }
10358   } else {
10359     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10360   }
10361 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10362   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10363     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10364     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10365   }
10366 #endif
10367   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10368   PetscFunctionReturn(PETSC_SUCCESS);
10369 }
10370 
10371 /*@C
10372   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10373   a given `Mat`. Each submatrix can span multiple procs.
10374 
10375   Collective
10376 
10377   Input Parameters:
10378 + mat     - the matrix
10379 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10380 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10381 
10382   Output Parameter:
10383 . subMat - parallel sub-matrices each spanning a given `subcomm`
10384 
10385   Level: advanced
10386 
10387   Notes:
10388   The submatrix partition across processors is dictated by `subComm` a
10389   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10390   is not restricted to be grouped with consecutive original ranks.
10391 
10392   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10393   map directly to the layout of the original matrix [wrt the local
10394   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10395   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10396   the `subMat`. However the offDiagMat looses some columns - and this is
10397   reconstructed with `MatSetValues()`
10398 
10399   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10400 
10401 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10402 @*/
10403 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10404 {
10405   PetscMPIInt commsize, subCommSize;
10406 
10407   PetscFunctionBegin;
10408   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10409   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10410   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10411 
10412   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");
10413   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10414   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10415   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10416   PetscFunctionReturn(PETSC_SUCCESS);
10417 }
10418 
10419 /*@
10420   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10421 
10422   Not Collective
10423 
10424   Input Parameters:
10425 + mat   - matrix to extract local submatrix from
10426 . isrow - local row indices for submatrix
10427 - iscol - local column indices for submatrix
10428 
10429   Output Parameter:
10430 . submat - the submatrix
10431 
10432   Level: intermediate
10433 
10434   Notes:
10435   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10436 
10437   Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10438   the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10439 
10440   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10441   `MatSetValuesBlockedLocal()` will also be implemented.
10442 
10443   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10444   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10445 
10446 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10447 @*/
10448 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10449 {
10450   PetscFunctionBegin;
10451   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10452   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10453   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10454   PetscCheckSameComm(isrow, 2, iscol, 3);
10455   PetscAssertPointer(submat, 4);
10456   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10457 
10458   if (mat->ops->getlocalsubmatrix) {
10459     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10460   } else {
10461     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10462   }
10463   PetscFunctionReturn(PETSC_SUCCESS);
10464 }
10465 
10466 /*@
10467   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10468 
10469   Not Collective
10470 
10471   Input Parameters:
10472 + mat    - matrix to extract local submatrix from
10473 . isrow  - local row indices for submatrix
10474 . iscol  - local column indices for submatrix
10475 - submat - the submatrix
10476 
10477   Level: intermediate
10478 
10479 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10480 @*/
10481 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10482 {
10483   PetscFunctionBegin;
10484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10485   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10486   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10487   PetscCheckSameComm(isrow, 2, iscol, 3);
10488   PetscAssertPointer(submat, 4);
10489   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10490 
10491   if (mat->ops->restorelocalsubmatrix) {
10492     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10493   } else {
10494     PetscCall(MatDestroy(submat));
10495   }
10496   *submat = NULL;
10497   PetscFunctionReturn(PETSC_SUCCESS);
10498 }
10499 
10500 /*@
10501   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10502 
10503   Collective
10504 
10505   Input Parameter:
10506 . mat - the matrix
10507 
10508   Output Parameter:
10509 . is - if any rows have zero diagonals this contains the list of them
10510 
10511   Level: developer
10512 
10513 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10514 @*/
10515 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10516 {
10517   PetscFunctionBegin;
10518   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10519   PetscValidType(mat, 1);
10520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10522 
10523   if (!mat->ops->findzerodiagonals) {
10524     Vec                diag;
10525     const PetscScalar *a;
10526     PetscInt          *rows;
10527     PetscInt           rStart, rEnd, r, nrow = 0;
10528 
10529     PetscCall(MatCreateVecs(mat, &diag, NULL));
10530     PetscCall(MatGetDiagonal(mat, diag));
10531     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10532     PetscCall(VecGetArrayRead(diag, &a));
10533     for (r = 0; r < rEnd - rStart; ++r)
10534       if (a[r] == 0.0) ++nrow;
10535     PetscCall(PetscMalloc1(nrow, &rows));
10536     nrow = 0;
10537     for (r = 0; r < rEnd - rStart; ++r)
10538       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10539     PetscCall(VecRestoreArrayRead(diag, &a));
10540     PetscCall(VecDestroy(&diag));
10541     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10542   } else {
10543     PetscUseTypeMethod(mat, findzerodiagonals, is);
10544   }
10545   PetscFunctionReturn(PETSC_SUCCESS);
10546 }
10547 
10548 /*@
10549   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10550 
10551   Collective
10552 
10553   Input Parameter:
10554 . mat - the matrix
10555 
10556   Output Parameter:
10557 . is - contains the list of rows with off block diagonal entries
10558 
10559   Level: developer
10560 
10561 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10562 @*/
10563 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10564 {
10565   PetscFunctionBegin;
10566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10567   PetscValidType(mat, 1);
10568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10570 
10571   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10572   PetscFunctionReturn(PETSC_SUCCESS);
10573 }
10574 
10575 /*@C
10576   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10577 
10578   Collective; No Fortran Support
10579 
10580   Input Parameter:
10581 . mat - the matrix
10582 
10583   Output Parameter:
10584 . values - the block inverses in column major order (FORTRAN-like)
10585 
10586   Level: advanced
10587 
10588   Notes:
10589   The size of the blocks is determined by the block size of the matrix.
10590 
10591   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10592 
10593   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10594 
10595 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10596 @*/
10597 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10598 {
10599   PetscFunctionBegin;
10600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10601   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10602   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10603   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10604   PetscFunctionReturn(PETSC_SUCCESS);
10605 }
10606 
10607 /*@C
10608   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10609 
10610   Collective; No Fortran Support
10611 
10612   Input Parameters:
10613 + mat     - the matrix
10614 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10615 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10616 
10617   Output Parameter:
10618 . values - the block inverses in column major order (FORTRAN-like)
10619 
10620   Level: advanced
10621 
10622   Notes:
10623   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10624 
10625   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10626 
10627 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10628 @*/
10629 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10630 {
10631   PetscFunctionBegin;
10632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10633   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10634   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10635   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10636   PetscFunctionReturn(PETSC_SUCCESS);
10637 }
10638 
10639 /*@
10640   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10641 
10642   Collective
10643 
10644   Input Parameters:
10645 + A - the matrix
10646 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10647 
10648   Level: advanced
10649 
10650   Note:
10651   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10652 
10653 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10654 @*/
10655 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10656 {
10657   const PetscScalar *vals;
10658   PetscInt          *dnnz;
10659   PetscInt           m, rstart, rend, bs, i, j;
10660 
10661   PetscFunctionBegin;
10662   PetscCall(MatInvertBlockDiagonal(A, &vals));
10663   PetscCall(MatGetBlockSize(A, &bs));
10664   PetscCall(MatGetLocalSize(A, &m, NULL));
10665   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10666   PetscCall(PetscMalloc1(m / bs, &dnnz));
10667   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10668   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10669   PetscCall(PetscFree(dnnz));
10670   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10671   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10672   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10673   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10674   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10675   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10676   PetscFunctionReturn(PETSC_SUCCESS);
10677 }
10678 
10679 /*@C
10680   MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10681   via `MatTransposeColoringCreate()`.
10682 
10683   Collective
10684 
10685   Input Parameter:
10686 . c - coloring context
10687 
10688   Level: intermediate
10689 
10690 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10691 @*/
10692 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10693 {
10694   MatTransposeColoring matcolor = *c;
10695 
10696   PetscFunctionBegin;
10697   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10698   if (--((PetscObject)matcolor)->refct > 0) {
10699     matcolor = NULL;
10700     PetscFunctionReturn(PETSC_SUCCESS);
10701   }
10702 
10703   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10704   PetscCall(PetscFree(matcolor->rows));
10705   PetscCall(PetscFree(matcolor->den2sp));
10706   PetscCall(PetscFree(matcolor->colorforcol));
10707   PetscCall(PetscFree(matcolor->columns));
10708   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10709   PetscCall(PetscHeaderDestroy(c));
10710   PetscFunctionReturn(PETSC_SUCCESS);
10711 }
10712 
10713 /*@C
10714   MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10715   a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10716   `MatTransposeColoring` to sparse B.
10717 
10718   Collective
10719 
10720   Input Parameters:
10721 + coloring - coloring context created with `MatTransposeColoringCreate()`
10722 - B        - sparse matrix
10723 
10724   Output Parameter:
10725 . Btdense - dense matrix B^T
10726 
10727   Level: developer
10728 
10729   Note:
10730   These are used internally for some implementations of `MatRARt()`
10731 
10732 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10733 @*/
10734 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10735 {
10736   PetscFunctionBegin;
10737   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10738   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10739   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10740 
10741   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10742   PetscFunctionReturn(PETSC_SUCCESS);
10743 }
10744 
10745 /*@C
10746   MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10747   a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10748   in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10749   `Csp` from `Cden`.
10750 
10751   Collective
10752 
10753   Input Parameters:
10754 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10755 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10756 
10757   Output Parameter:
10758 . Csp - sparse matrix
10759 
10760   Level: developer
10761 
10762   Note:
10763   These are used internally for some implementations of `MatRARt()`
10764 
10765 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10766 @*/
10767 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10768 {
10769   PetscFunctionBegin;
10770   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10771   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10772   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10773 
10774   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10775   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10776   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10777   PetscFunctionReturn(PETSC_SUCCESS);
10778 }
10779 
10780 /*@C
10781   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10782 
10783   Collective
10784 
10785   Input Parameters:
10786 + mat        - the matrix product C
10787 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10788 
10789   Output Parameter:
10790 . color - the new coloring context
10791 
10792   Level: intermediate
10793 
10794 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10795           `MatTransColoringApplyDenToSp()`
10796 @*/
10797 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10798 {
10799   MatTransposeColoring c;
10800   MPI_Comm             comm;
10801 
10802   PetscFunctionBegin;
10803   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10804   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10805   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10806 
10807   c->ctype = iscoloring->ctype;
10808   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10809 
10810   *color = c;
10811   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10812   PetscFunctionReturn(PETSC_SUCCESS);
10813 }
10814 
10815 /*@
10816   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10817   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10818   same, otherwise it will be larger
10819 
10820   Not Collective
10821 
10822   Input Parameter:
10823 . mat - the matrix
10824 
10825   Output Parameter:
10826 . state - the current state
10827 
10828   Level: intermediate
10829 
10830   Notes:
10831   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10832   different matrices
10833 
10834   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10835 
10836   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10837 
10838 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10839 @*/
10840 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10841 {
10842   PetscFunctionBegin;
10843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10844   *state = mat->nonzerostate;
10845   PetscFunctionReturn(PETSC_SUCCESS);
10846 }
10847 
10848 /*@
10849   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10850   matrices from each processor
10851 
10852   Collective
10853 
10854   Input Parameters:
10855 + comm   - the communicators the parallel matrix will live on
10856 . seqmat - the input sequential matrices
10857 . n      - number of local columns (or `PETSC_DECIDE`)
10858 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10859 
10860   Output Parameter:
10861 . mpimat - the parallel matrix generated
10862 
10863   Level: developer
10864 
10865   Note:
10866   The number of columns of the matrix in EACH processor MUST be the same.
10867 
10868 .seealso: [](ch_matrices), `Mat`
10869 @*/
10870 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10871 {
10872   PetscMPIInt size;
10873 
10874   PetscFunctionBegin;
10875   PetscCallMPI(MPI_Comm_size(comm, &size));
10876   if (size == 1) {
10877     if (reuse == MAT_INITIAL_MATRIX) {
10878       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10879     } else {
10880       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10881     }
10882     PetscFunctionReturn(PETSC_SUCCESS);
10883   }
10884 
10885   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");
10886 
10887   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10888   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10889   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10890   PetscFunctionReturn(PETSC_SUCCESS);
10891 }
10892 
10893 /*@
10894   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10895 
10896   Collective
10897 
10898   Input Parameters:
10899 + A - the matrix to create subdomains from
10900 - N - requested number of subdomains
10901 
10902   Output Parameters:
10903 + n   - number of subdomains resulting on this MPI process
10904 - iss - `IS` list with indices of subdomains on this MPI process
10905 
10906   Level: advanced
10907 
10908   Note:
10909   The number of subdomains must be smaller than the communicator size
10910 
10911 .seealso: [](ch_matrices), `Mat`, `IS`
10912 @*/
10913 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10914 {
10915   MPI_Comm    comm, subcomm;
10916   PetscMPIInt size, rank, color;
10917   PetscInt    rstart, rend, k;
10918 
10919   PetscFunctionBegin;
10920   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10921   PetscCallMPI(MPI_Comm_size(comm, &size));
10922   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10923   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);
10924   *n    = 1;
10925   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10926   color = rank / k;
10927   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10928   PetscCall(PetscMalloc1(1, iss));
10929   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10930   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10931   PetscCallMPI(MPI_Comm_free(&subcomm));
10932   PetscFunctionReturn(PETSC_SUCCESS);
10933 }
10934 
10935 /*@
10936   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10937 
10938   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10939   If they are not the same, uses `MatMatMatMult()`.
10940 
10941   Once the coarse grid problem is constructed, correct for interpolation operators
10942   that are not of full rank, which can legitimately happen in the case of non-nested
10943   geometric multigrid.
10944 
10945   Input Parameters:
10946 + restrct     - restriction operator
10947 . dA          - fine grid matrix
10948 . interpolate - interpolation operator
10949 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10950 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10951 
10952   Output Parameter:
10953 . A - the Galerkin coarse matrix
10954 
10955   Options Database Key:
10956 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10957 
10958   Level: developer
10959 
10960 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10961 @*/
10962 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10963 {
10964   IS  zerorows;
10965   Vec diag;
10966 
10967   PetscFunctionBegin;
10968   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10969   /* Construct the coarse grid matrix */
10970   if (interpolate == restrct) {
10971     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10972   } else {
10973     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10974   }
10975 
10976   /* If the interpolation matrix is not of full rank, A will have zero rows.
10977      This can legitimately happen in the case of non-nested geometric multigrid.
10978      In that event, we set the rows of the matrix to the rows of the identity,
10979      ignoring the equations (as the RHS will also be zero). */
10980 
10981   PetscCall(MatFindZeroRows(*A, &zerorows));
10982 
10983   if (zerorows != NULL) { /* if there are any zero rows */
10984     PetscCall(MatCreateVecs(*A, &diag, NULL));
10985     PetscCall(MatGetDiagonal(*A, diag));
10986     PetscCall(VecISSet(diag, zerorows, 1.0));
10987     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10988     PetscCall(VecDestroy(&diag));
10989     PetscCall(ISDestroy(&zerorows));
10990   }
10991   PetscFunctionReturn(PETSC_SUCCESS);
10992 }
10993 
10994 /*@C
10995   MatSetOperation - Allows user to set a matrix operation for any matrix type
10996 
10997   Logically Collective
10998 
10999   Input Parameters:
11000 + mat - the matrix
11001 . op  - the name of the operation
11002 - f   - the function that provides the operation
11003 
11004   Level: developer
11005 
11006   Example Usage:
11007 .vb
11008   extern PetscErrorCode usermult(Mat, Vec, Vec);
11009 
11010   PetscCall(MatCreateXXX(comm, ..., &A));
11011   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11012 .ve
11013 
11014   Notes:
11015   See the file `include/petscmat.h` for a complete list of matrix
11016   operations, which all have the form MATOP_<OPERATION>, where
11017   <OPERATION> is the name (in all capital letters) of the
11018   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11019 
11020   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11021   sequence as the usual matrix interface routines, since they
11022   are intended to be accessed via the usual matrix interface
11023   routines, e.g.,
11024 .vb
11025   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11026 .ve
11027 
11028   In particular each function MUST return `PETSC_SUCCESS` on success and
11029   nonzero on failure.
11030 
11031   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11032 
11033 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11034 @*/
11035 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11036 {
11037   PetscFunctionBegin;
11038   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11039   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11040   (((void (**)(void))mat->ops)[op]) = f;
11041   PetscFunctionReturn(PETSC_SUCCESS);
11042 }
11043 
11044 /*@C
11045   MatGetOperation - Gets a matrix operation for any matrix type.
11046 
11047   Not Collective
11048 
11049   Input Parameters:
11050 + mat - the matrix
11051 - op  - the name of the operation
11052 
11053   Output Parameter:
11054 . f - the function that provides the operation
11055 
11056   Level: developer
11057 
11058   Example Usage:
11059 .vb
11060   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11061 
11062   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11063 .ve
11064 
11065   Notes:
11066   See the file include/petscmat.h for a complete list of matrix
11067   operations, which all have the form MATOP_<OPERATION>, where
11068   <OPERATION> is the name (in all capital letters) of the
11069   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11070 
11071   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11072 
11073 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11074 @*/
11075 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11076 {
11077   PetscFunctionBegin;
11078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11079   *f = (((void (**)(void))mat->ops)[op]);
11080   PetscFunctionReturn(PETSC_SUCCESS);
11081 }
11082 
11083 /*@
11084   MatHasOperation - Determines whether the given matrix supports the particular operation.
11085 
11086   Not Collective
11087 
11088   Input Parameters:
11089 + mat - the matrix
11090 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11091 
11092   Output Parameter:
11093 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11094 
11095   Level: advanced
11096 
11097   Note:
11098   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11099 
11100 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11101 @*/
11102 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11103 {
11104   PetscFunctionBegin;
11105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11106   PetscAssertPointer(has, 3);
11107   if (mat->ops->hasoperation) {
11108     PetscUseTypeMethod(mat, hasoperation, op, has);
11109   } else {
11110     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11111     else {
11112       *has = PETSC_FALSE;
11113       if (op == MATOP_CREATE_SUBMATRIX) {
11114         PetscMPIInt size;
11115 
11116         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11117         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11118       }
11119     }
11120   }
11121   PetscFunctionReturn(PETSC_SUCCESS);
11122 }
11123 
11124 /*@
11125   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11126 
11127   Collective
11128 
11129   Input Parameter:
11130 . mat - the matrix
11131 
11132   Output Parameter:
11133 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11134 
11135   Level: beginner
11136 
11137 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11138 @*/
11139 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11140 {
11141   PetscFunctionBegin;
11142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11143   PetscValidType(mat, 1);
11144   PetscAssertPointer(cong, 2);
11145   if (!mat->rmap || !mat->cmap) {
11146     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11147     PetscFunctionReturn(PETSC_SUCCESS);
11148   }
11149   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11150     PetscCall(PetscLayoutSetUp(mat->rmap));
11151     PetscCall(PetscLayoutSetUp(mat->cmap));
11152     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11153     if (*cong) mat->congruentlayouts = 1;
11154     else mat->congruentlayouts = 0;
11155   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11156   PetscFunctionReturn(PETSC_SUCCESS);
11157 }
11158 
11159 PetscErrorCode MatSetInf(Mat A)
11160 {
11161   PetscFunctionBegin;
11162   PetscUseTypeMethod(A, setinf);
11163   PetscFunctionReturn(PETSC_SUCCESS);
11164 }
11165 
11166 /*@C
11167   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
11168   and possibly removes small values from the graph structure.
11169 
11170   Collective
11171 
11172   Input Parameters:
11173 + A      - the matrix
11174 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11175 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11176 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11177 
11178   Output Parameter:
11179 . graph - the resulting graph
11180 
11181   Level: advanced
11182 
11183 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11184 @*/
11185 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11186 {
11187   PetscFunctionBegin;
11188   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11189   PetscValidType(A, 1);
11190   PetscValidLogicalCollectiveBool(A, scale, 3);
11191   PetscAssertPointer(graph, 5);
11192   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11193   PetscFunctionReturn(PETSC_SUCCESS);
11194 }
11195 
11196 /*@
11197   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11198   meaning the same memory is used for the matrix, and no new memory is allocated.
11199 
11200   Collective
11201 
11202   Input Parameters:
11203 + A    - the matrix
11204 - 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
11205 
11206   Level: intermediate
11207 
11208   Developer Notes:
11209   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11210   of the arrays in the data structure are unneeded.
11211 
11212 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11213 @*/
11214 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11215 {
11216   PetscFunctionBegin;
11217   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11218   PetscUseTypeMethod(A, eliminatezeros, keep);
11219   PetscFunctionReturn(PETSC_SUCCESS);
11220 }
11221