xref: /petsc/src/mat/interface/matrix.c (revision 28d911a8077fa87b9a4a10e8dbd0dedeb22bcffd)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 . mat - the matrix
257 
258   Output Parameter:
259 . keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264   `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscAssertPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282   MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 . mat - the matrix
286 
287   Output Parameter:
288 . zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293   `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscAssertPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323   Not Collective
324 
325   Input Parameter:
326 . A - the matrix
327 
328   Output Parameter:
329 . a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331   Level: advanced
332 
333   Notes:
334   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscAssertPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361   Collective
362 
363   Input Parameter:
364 . mat - the matrix
365 
366   Output Parameter:
367 . trace - the sum of the diagonal entries
368 
369   Level: advanced
370 
371 .seealso: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388   MatRealPart - Zeros out the imaginary part of the matrix
389 
390   Logically Collective
391 
392   Input Parameter:
393 . mat - the matrix
394 
395   Level: advanced
396 
397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414   Collective
415 
416   Input Parameter:
417 . mat - the matrix
418 
419   Output Parameters:
420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
421 - ghosts  - the global indices of the ghost points
422 
423   Level: advanced
424 
425   Note:
426   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
427 
428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448   Logically Collective
449 
450   Input Parameter:
451 . mat - the matrix
452 
453   Level: advanced
454 
455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
471 
472   Not Collective
473 
474   Input Parameter:
475 . mat - the matrix
476 
477   Output Parameters:
478 + missing - is any diagonal entry missing
479 - dd      - first diagonal entry that is missing (optional) on this process
480 
481   Level: advanced
482 
483   Note:
484   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
485 
486 .seealso: [](ch_matrices), `Mat`
487 @*/
488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
489 {
490   PetscFunctionBegin;
491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
492   PetscValidType(mat, 1);
493   PetscAssertPointer(missing, 2);
494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
496   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
497   PetscFunctionReturn(PETSC_SUCCESS);
498 }
499 
500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
501 /*@C
502   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
503   for each row that you get to ensure that your application does
504   not bleed memory.
505 
506   Not Collective
507 
508   Input Parameters:
509 + mat - the matrix
510 - row - the row to get
511 
512   Output Parameters:
513 + ncols - if not `NULL`, the number of nonzeros in `row`
514 . cols  - if not `NULL`, the column numbers
515 - vals  - if not `NULL`, the numerical values
516 
517   Level: advanced
518 
519   Notes:
520   This routine is provided for people who need to have direct access
521   to the structure of a matrix.  We hope that we provide enough
522   high-level matrix routines that few users will need it.
523 
524   `MatGetRow()` always returns 0-based column indices, regardless of
525   whether the internal representation is 0-based (default) or 1-based.
526 
527   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
528   not wish to extract these quantities.
529 
530   The user can only examine the values extracted with `MatGetRow()`;
531   the values CANNOT be altered.  To change the matrix entries, one
532   must use `MatSetValues()`.
533 
534   You can only have one call to `MatGetRow()` outstanding for a particular
535   matrix at a time, per processor. `MatGetRow()` can only obtain rows
536   associated with the given processor, it cannot get rows from the
537   other processors; for that we suggest using `MatCreateSubMatrices()`, then
538   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
539   is in the global number of rows.
540 
541   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
542 
543   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
544 
545   Fortran Note:
546   The calling sequence is
547 .vb
548    MatGetRow(matrix,row,ncols,cols,values,ierr)
549          Mat     matrix (input)
550          integer row    (input)
551          integer ncols  (output)
552          integer cols(maxcols) (output)
553          double precision (or double complex) values(maxcols) output
554 .ve
555   where maxcols >= maximum nonzeros in any row of the matrix.
556 
557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578   MatConjugate - replaces the matrix values with their complex conjugates
579 
580   Logically Collective
581 
582   Input Parameter:
583 . mat - the matrix
584 
585   Level: advanced
586 
587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604   Not Collective
605 
606   Input Parameters:
607 + mat   - the matrix
608 . row   - the row to get
609 . ncols - the number of nonzeros
610 . cols  - the columns of the nonzeros
611 - vals  - if nonzero the column values
612 
613   Level: advanced
614 
615   Notes:
616   This routine should be called after you have finished examining the entries.
617 
618   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619   us of the array after it has been restored. If you pass `NULL`, it will
620   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622   Fortran Notes:
623   The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632   Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635   before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscAssertPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657   Not Collective
658 
659   Input Parameter:
660 . mat - the matrix
661 
662   Level: advanced
663 
664   Note:
665   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
666 
667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685   Not Collective
686 
687   Input Parameter:
688 . mat - the matrix
689 
690   Level: advanced
691 
692   Note:
693   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711   MatSetOptionsPrefix - Sets the prefix used for searching for all
712   `Mat` options in the database.
713 
714   Logically Collective
715 
716   Input Parameters:
717 + A      - the matrix
718 - prefix - the prefix to prepend to all option names
719 
720   Level: advanced
721 
722   Notes:
723   A hyphen (-) must NOT be given at the beginning of the prefix name.
724   The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726   This is NOT used for options for the factorization of the matrix. Normally the
727   prefix is automatically passed in from the PC calling the factorization. To set
728   it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742   for matrices created with `MatGetFactor()`
743 
744   Logically Collective
745 
746   Input Parameters:
747 + A      - the matrix
748 - prefix - the prefix to prepend to all option names for the factored matrix
749 
750   Level: developer
751 
752   Notes:
753   A hyphen (-) must NOT be given at the beginning of the prefix name.
754   The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscAssertPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778   for matrices created with `MatGetFactor()`
779 
780   Logically Collective
781 
782   Input Parameters:
783 + A      - the matrix
784 - prefix - the prefix to prepend to all option names for the factored matrix
785 
786   Level: developer
787 
788   Notes:
789   A hyphen (-) must NOT be given at the beginning of the prefix name.
790   The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822   matrix options in the database.
823 
824   Logically Collective
825 
826   Input Parameters:
827 + A      - the matrix
828 - prefix - the prefix to prepend to all option names
829 
830   Level: advanced
831 
832   Note:
833   A hyphen (-) must NOT be given at the beginning of the prefix name.
834   The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847   MatGetOptionsPrefix - Gets the prefix used for searching for all
848   matrix options in the database.
849 
850   Not Collective
851 
852   Input Parameter:
853 . A - the matrix
854 
855   Output Parameter:
856 . prefix - pointer to the prefix string used
857 
858   Level: advanced
859 
860   Fortran Note:
861   The user should pass in a string `prefix` of
862   sufficient length to hold the prefix.
863 
864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscAssertPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
877 
878   Collective
879 
880   Input Parameter:
881 . A - the matrix
882 
883   Level: beginner
884 
885   Notes:
886   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888   Users can reset the preallocation to access the original memory.
889 
890   Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
900   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
901   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
902   PetscFunctionReturn(PETSC_SUCCESS);
903 }
904 
905 /*@
906   MatSetUp - Sets up the internal matrix data structures for later use.
907 
908   Collective
909 
910   Input Parameter:
911 . A - the matrix
912 
913   Level: intermediate
914 
915   Notes:
916   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
917   setting values in the matrix.
918 
919   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*
945    If threadsafety is on extraneous matrices may be printed
946 
947    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
948 */
949 #if !defined(PETSC_HAVE_THREADSAFETY)
950 static PetscInt insidematview = 0;
951 #endif
952 
953 /*@C
954   MatViewFromOptions - View properties of the matrix based on options set in the options database
955 
956   Collective
957 
958   Input Parameters:
959 + A    - the matrix
960 . obj  - optional additional object that provides the options prefix to use
961 - name - command line option
962 
963   Options Database Key:
964 . -mat_view [viewertype]:... - the viewer and its options
965 
966   Level: intermediate
967 
968   Note:
969 .vb
970     If no value is provided ascii:stdout is used
971        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
972                                                   for example ascii::ascii_info prints just the information about the object not all details
973                                                   unless :append is given filename opens in write mode, overwriting what was already there
974        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
975        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
976        socket[:port]                             defaults to the standard output port
977        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
978 .ve
979 
980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
981 @*/
982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
983 {
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
986 #if !defined(PETSC_HAVE_THREADSAFETY)
987   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
988 #endif
989   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
990   PetscFunctionReturn(PETSC_SUCCESS);
991 }
992 
993 /*@C
994   MatView - display information about a matrix in a variety ways
995 
996   Collective
997 
998   Input Parameters:
999 + mat    - the matrix
1000 - viewer - visualization context
1001 
1002   Options Database Keys:
1003 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1004 . -mat_view ::ascii_info_detail    - Prints more detailed info
1005 . -mat_view                        - Prints matrix in ASCII format
1006 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1007 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1008 . -display <name>                  - Sets display name (default is host)
1009 . -draw_pause <sec>                - Sets number of seconds to pause after display
1010 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1011 . -viewer_socket_machine <machine> - -
1012 . -viewer_socket_port <port>       - -
1013 . -mat_view binary                 - save matrix to file in binary format
1014 - -viewer_binary_filename <name>   - -
1015 
1016   Level: beginner
1017 
1018   Notes:
1019   The available visualization contexts include
1020 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1021 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1022 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1023 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1024 
1025   The user can open alternative visualization contexts with
1026 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1027 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1028   specified file; corresponding input uses `MatLoad()`
1029 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1030   an X window display
1031 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1032   Currently only the `MATSEQDENSE` and `MATAIJ`
1033   matrix types support the Socket viewer.
1034 
1035   The user can call `PetscViewerPushFormat()` to specify the output
1036   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1037   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1038 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1039 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1040 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1041 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1042   format common among all matrix types
1043 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1044   format (which is in many cases the same as the default)
1045 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1046   size and structure (not the matrix entries)
1047 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1048   the matrix structure
1049 
1050   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1051   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1052 
1053   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1054 
1055   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1056   viewer is used.
1057 
1058   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1059   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1060 
1061   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1062   and then use the following mouse functions.
1063 .vb
1064   left mouse: zoom in
1065   middle mouse: zoom out
1066   right mouse: continue with the simulation
1067 .ve
1068 
1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1070           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1071 @*/
1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1073 {
1074   PetscInt          rows, cols, rbs, cbs;
1075   PetscBool         isascii, isstring, issaws;
1076   PetscViewerFormat format;
1077   PetscMPIInt       size;
1078 
1079   PetscFunctionBegin;
1080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1081   PetscValidType(mat, 1);
1082   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1083   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1084   PetscCheckSameComm(mat, 1, viewer, 2);
1085 
1086   PetscCall(PetscViewerGetFormat(viewer, &format));
1087   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1088   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1089 
1090 #if !defined(PETSC_HAVE_THREADSAFETY)
1091   insidematview++;
1092 #endif
1093   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1096   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1097 
1098   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1099   if (isascii) {
1100     if (!mat->preallocated) {
1101       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1102 #if !defined(PETSC_HAVE_THREADSAFETY)
1103       insidematview--;
1104 #endif
1105       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1106       PetscFunctionReturn(PETSC_SUCCESS);
1107     }
1108     if (!mat->assembled) {
1109       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1110 #if !defined(PETSC_HAVE_THREADSAFETY)
1111       insidematview--;
1112 #endif
1113       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1114       PetscFunctionReturn(PETSC_SUCCESS);
1115     }
1116     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1117     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1118       MatNullSpace nullsp, transnullsp;
1119 
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatGetSize(mat, &rows, &cols));
1122       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1123       if (rbs != 1 || cbs != 1) {
1124         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1125         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1126       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1127       if (mat->factortype) {
1128         MatSolverType solver;
1129         PetscCall(MatFactorGetSolverType(mat, &solver));
1130         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1131       }
1132       if (mat->ops->getinfo) {
1133         MatInfo info;
1134         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1135         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1136         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1137       }
1138       PetscCall(MatGetNullSpace(mat, &nullsp));
1139       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1140       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1141       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1142       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1144       PetscCall(PetscViewerASCIIPushTab(viewer));
1145       PetscCall(MatProductView(mat, viewer));
1146       PetscCall(PetscViewerASCIIPopTab(viewer));
1147     }
1148   } else if (issaws) {
1149 #if defined(PETSC_HAVE_SAWS)
1150     PetscMPIInt rank;
1151 
1152     PetscCall(PetscObjectName((PetscObject)mat));
1153     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1154     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1155 #endif
1156   } else if (isstring) {
1157     const char *type;
1158     PetscCall(MatGetType(mat, &type));
1159     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1160     PetscTryTypeMethod(mat, view, viewer);
1161   }
1162   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1163     PetscCall(PetscViewerASCIIPushTab(viewer));
1164     PetscUseTypeMethod(mat, viewnative, viewer);
1165     PetscCall(PetscViewerASCIIPopTab(viewer));
1166   } else if (mat->ops->view) {
1167     PetscCall(PetscViewerASCIIPushTab(viewer));
1168     PetscUseTypeMethod(mat, view, viewer);
1169     PetscCall(PetscViewerASCIIPopTab(viewer));
1170   }
1171   if (isascii) {
1172     PetscCall(PetscViewerGetFormat(viewer, &format));
1173     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1174   }
1175   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1176 #if !defined(PETSC_HAVE_THREADSAFETY)
1177   insidematview--;
1178 #endif
1179   PetscFunctionReturn(PETSC_SUCCESS);
1180 }
1181 
1182 #if defined(PETSC_USE_DEBUG)
1183   #include <../src/sys/totalview/tv_data_display.h>
1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1185 {
1186   TV_add_row("Local rows", "int", &mat->rmap->n);
1187   TV_add_row("Local columns", "int", &mat->cmap->n);
1188   TV_add_row("Global rows", "int", &mat->rmap->N);
1189   TV_add_row("Global columns", "int", &mat->cmap->N);
1190   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1191   return TV_format_OK;
1192 }
1193 #endif
1194 
1195 /*@C
1196   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1197   with `MatView()`.  The matrix format is determined from the options database.
1198   Generates a parallel MPI matrix if the communicator has more than one
1199   processor.  The default matrix type is `MATAIJ`.
1200 
1201   Collective
1202 
1203   Input Parameters:
1204 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1205             or some related function before a call to `MatLoad()`
1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1207 
1208   Options Database Keys:
1209    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1210    block size
1211 . -matload_block_size <bs> - set block size
1212 
1213   Level: beginner
1214 
1215   Notes:
1216   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1217   `Mat` before calling this routine if you wish to set it from the options database.
1218 
1219   `MatLoad()` automatically loads into the options database any options
1220   given in the file filename.info where filename is the name of the file
1221   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1222   file will be ignored if you use the -viewer_binary_skip_info option.
1223 
1224   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1225   sets the default matrix type AIJ and sets the local and global sizes.
1226   If type and/or size is already set, then the same are used.
1227 
1228   In parallel, each processor can load a subset of rows (or the
1229   entire matrix).  This routine is especially useful when a large
1230   matrix is stored on disk and only part of it is desired on each
1231   processor.  For example, a parallel solver may access only some of
1232   the rows from each processor.  The algorithm used here reads
1233   relatively small blocks of data rather than reading the entire
1234   matrix and then subsetting it.
1235 
1236   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1237   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1238   or the sequence like
1239 .vb
1240     `PetscViewer` v;
1241     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1242     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1243     `PetscViewerSetFromOptions`(v);
1244     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1245     `PetscViewerFileSetName`(v,"datafile");
1246 .ve
1247   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1248 $ -viewer_type {binary, hdf5}
1249 
1250   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1251   and src/mat/tutorials/ex10.c with the second approach.
1252 
1253   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1254   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1255   Multiple objects, both matrices and vectors, can be stored within the same file.
1256   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1257 
1258   Most users should not need to know the details of the binary storage
1259   format, since `MatLoad()` and `MatView()` completely hide these details.
1260   But for anyone who is interested, the standard binary matrix storage
1261   format is
1262 
1263 .vb
1264     PetscInt    MAT_FILE_CLASSID
1265     PetscInt    number of rows
1266     PetscInt    number of columns
1267     PetscInt    total number of nonzeros
1268     PetscInt    *number nonzeros in each row
1269     PetscInt    *column indices of all nonzeros (starting index is zero)
1270     PetscScalar *values of all nonzeros
1271 .ve
1272   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1273   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
1274   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1275 
1276   PETSc automatically does the byte swapping for
1277   machines that store the bytes reversed. Thus if you write your own binary
1278   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1279   and `PetscBinaryWrite()` to see how this may be done.
1280 
1281   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1282   Each processor's chunk is loaded independently by its owning MPI process.
1283   Multiple objects, both matrices and vectors, can be stored within the same file.
1284   They are looked up by their PetscObject name.
1285 
1286   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1287   by default the same structure and naming of the AIJ arrays and column count
1288   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1289 $    save example.mat A b -v7.3
1290   can be directly read by this routine (see Reference 1 for details).
1291 
1292   Depending on your MATLAB version, this format might be a default,
1293   otherwise you can set it as default in Preferences.
1294 
1295   Unless -nocompression flag is used to save the file in MATLAB,
1296   PETSc must be configured with ZLIB package.
1297 
1298   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1299 
1300   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1301 
1302   Corresponding `MatView()` is not yet implemented.
1303 
1304   The loaded matrix is actually a transpose of the original one in MATLAB,
1305   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1306   With this format, matrix is automatically transposed by PETSc,
1307   unless the matrix is marked as SPD or symmetric
1308   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1309 
1310   References:
1311 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1312 
1313 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1314  @*/
1315 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1316 {
1317   PetscBool flg;
1318 
1319   PetscFunctionBegin;
1320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1321   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1322 
1323   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1324 
1325   flg = PETSC_FALSE;
1326   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1327   if (flg) {
1328     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1329     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1330   }
1331   flg = PETSC_FALSE;
1332   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1333   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1334 
1335   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1336   PetscUseTypeMethod(mat, load, viewer);
1337   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1338   PetscFunctionReturn(PETSC_SUCCESS);
1339 }
1340 
1341 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1342 {
1343   Mat_Redundant *redund = *redundant;
1344 
1345   PetscFunctionBegin;
1346   if (redund) {
1347     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1348       PetscCall(ISDestroy(&redund->isrow));
1349       PetscCall(ISDestroy(&redund->iscol));
1350       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1351     } else {
1352       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1353       PetscCall(PetscFree(redund->sbuf_j));
1354       PetscCall(PetscFree(redund->sbuf_a));
1355       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1356         PetscCall(PetscFree(redund->rbuf_j[i]));
1357         PetscCall(PetscFree(redund->rbuf_a[i]));
1358       }
1359       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1360     }
1361 
1362     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1363     PetscCall(PetscFree(redund));
1364   }
1365   PetscFunctionReturn(PETSC_SUCCESS);
1366 }
1367 
1368 /*@C
1369   MatDestroy - Frees space taken by a matrix.
1370 
1371   Collective
1372 
1373   Input Parameter:
1374 . A - the matrix
1375 
1376   Level: beginner
1377 
1378   Developer Note:
1379   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1380   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1381   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1382   if changes are needed here.
1383 
1384 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1385 @*/
1386 PetscErrorCode MatDestroy(Mat *A)
1387 {
1388   PetscFunctionBegin;
1389   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1390   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1391   if (--((PetscObject)(*A))->refct > 0) {
1392     *A = NULL;
1393     PetscFunctionReturn(PETSC_SUCCESS);
1394   }
1395 
1396   /* if memory was published with SAWs then destroy it */
1397   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1398   PetscTryTypeMethod((*A), destroy);
1399 
1400   PetscCall(PetscFree((*A)->factorprefix));
1401   PetscCall(PetscFree((*A)->defaultvectype));
1402   PetscCall(PetscFree((*A)->defaultrandtype));
1403   PetscCall(PetscFree((*A)->bsizes));
1404   PetscCall(PetscFree((*A)->solvertype));
1405   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1406   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1407   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1408   PetscCall(MatProductClear(*A));
1409   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1411   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1412   PetscCall(MatDestroy(&(*A)->schur));
1413   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1414   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1415   PetscCall(PetscHeaderDestroy(A));
1416   PetscFunctionReturn(PETSC_SUCCESS);
1417 }
1418 
1419 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1420 /*@C
1421   MatSetValues - Inserts or adds a block of values into a matrix.
1422   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1423   MUST be called after all calls to `MatSetValues()` have been completed.
1424 
1425   Not Collective
1426 
1427   Input Parameters:
1428 + mat  - the matrix
1429 . v    - a logically two-dimensional array of values
1430 . m    - the number of rows
1431 . idxm - the global indices of the rows
1432 . n    - the number of columns
1433 . idxn - the global indices of the columns
1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1435 
1436   Level: beginner
1437 
1438   Notes:
1439   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1440 
1441   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1442   options cannot be mixed without intervening calls to the assembly
1443   routines.
1444 
1445   `MatSetValues()` uses 0-based row and column numbers in Fortran
1446   as well as in C.
1447 
1448   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1449   simply ignored. This allows easily inserting element stiffness matrices
1450   with homogeneous Dirichlet boundary conditions that you don't want represented
1451   in the matrix.
1452 
1453   Efficiency Alert:
1454   The routine `MatSetValuesBlocked()` may offer much better efficiency
1455   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1456 
1457   Developer Note:
1458   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1459   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1460 
1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1462           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1463 @*/
1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1465 {
1466   PetscFunctionBeginHot;
1467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1468   PetscValidType(mat, 1);
1469   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1470   PetscAssertPointer(idxm, 3);
1471   PetscAssertPointer(idxn, 5);
1472   MatCheckPreallocated(mat, 1);
1473 
1474   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1475   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1476 
1477   if (PetscDefined(USE_DEBUG)) {
1478     PetscInt i, j;
1479 
1480     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1481     for (i = 0; i < m; i++) {
1482       for (j = 0; j < n; j++) {
1483         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1484 #if defined(PETSC_USE_COMPLEX)
1485           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]);
1486 #else
1487           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]);
1488 #endif
1489       }
1490     }
1491     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);
1492     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);
1493   }
1494 
1495   if (mat->assembled) {
1496     mat->was_assembled = PETSC_TRUE;
1497     mat->assembled     = PETSC_FALSE;
1498   }
1499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1500   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1501   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1502   PetscFunctionReturn(PETSC_SUCCESS);
1503 }
1504 
1505 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1506 /*@C
1507   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1508   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1509   MUST be called after all calls to `MatSetValues()` have been completed.
1510 
1511   Not Collective
1512 
1513   Input Parameters:
1514 + mat  - the matrix
1515 . v    - a logically two-dimensional array of values
1516 . ism  - the rows to provide
1517 . isn  - the columns to provide
1518 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1519 
1520   Level: beginner
1521 
1522   Notes:
1523   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1524 
1525   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1526   options cannot be mixed without intervening calls to the assembly
1527   routines.
1528 
1529   `MatSetValues()` uses 0-based row and column numbers in Fortran
1530   as well as in C.
1531 
1532   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1533   simply ignored. This allows easily inserting element stiffness matrices
1534   with homogeneous Dirichlet boundary conditions that you don't want represented
1535   in the matrix.
1536 
1537   Efficiency Alert:
1538   The routine `MatSetValuesBlocked()` may offer much better efficiency
1539   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1540 
1541   This is currently not optimized for any particular `ISType`
1542 
1543   Developer Note:
1544   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1545   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1546 
1547 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1548           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1549 @*/
1550 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1551 {
1552   PetscInt        m, n;
1553   const PetscInt *rows, *cols;
1554 
1555   PetscFunctionBeginHot;
1556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1557   PetscCall(ISGetIndices(ism, &rows));
1558   PetscCall(ISGetIndices(isn, &cols));
1559   PetscCall(ISGetLocalSize(ism, &m));
1560   PetscCall(ISGetLocalSize(isn, &n));
1561   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1562   PetscCall(ISRestoreIndices(ism, &rows));
1563   PetscCall(ISRestoreIndices(isn, &cols));
1564   PetscFunctionReturn(PETSC_SUCCESS);
1565 }
1566 
1567 /*@
1568   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1569   values into a matrix
1570 
1571   Not Collective
1572 
1573   Input Parameters:
1574 + mat - the matrix
1575 . row - the (block) row to set
1576 - v   - a logically two-dimensional array of values
1577 
1578   Level: intermediate
1579 
1580   Notes:
1581   The values, `v`, are column-oriented (for the block version) and sorted
1582 
1583   All the nonzero values in `row` must be provided
1584 
1585   The matrix must have previously had its column indices set, likely by having been assembled.
1586 
1587   `row` must belong to this MPI process
1588 
1589 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1590           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1591 @*/
1592 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1593 {
1594   PetscInt globalrow;
1595 
1596   PetscFunctionBegin;
1597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1598   PetscValidType(mat, 1);
1599   PetscAssertPointer(v, 3);
1600   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1601   PetscCall(MatSetValuesRow(mat, globalrow, v));
1602   PetscFunctionReturn(PETSC_SUCCESS);
1603 }
1604 
1605 /*@
1606   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1607   values into a matrix
1608 
1609   Not Collective
1610 
1611   Input Parameters:
1612 + mat - the matrix
1613 . row - the (block) row to set
1614 - 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
1615 
1616   Level: advanced
1617 
1618   Notes:
1619   The values, `v`, are column-oriented for the block version.
1620 
1621   All the nonzeros in `row` must be provided
1622 
1623   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1624 
1625   `row` must belong to this process
1626 
1627 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1628           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1629 @*/
1630 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1631 {
1632   PetscFunctionBeginHot;
1633   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1634   PetscValidType(mat, 1);
1635   MatCheckPreallocated(mat, 1);
1636   PetscAssertPointer(v, 3);
1637   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1638   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1639   mat->insertmode = INSERT_VALUES;
1640 
1641   if (mat->assembled) {
1642     mat->was_assembled = PETSC_TRUE;
1643     mat->assembled     = PETSC_FALSE;
1644   }
1645   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1646   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1647   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1648   PetscFunctionReturn(PETSC_SUCCESS);
1649 }
1650 
1651 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1652 /*@
1653   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1654   Using structured grid indexing
1655 
1656   Not Collective
1657 
1658   Input Parameters:
1659 + mat  - the matrix
1660 . m    - number of rows being entered
1661 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1662 . n    - number of columns being entered
1663 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1664 . v    - a logically two-dimensional array of values
1665 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1666 
1667   Level: beginner
1668 
1669   Notes:
1670   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1671 
1672   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1673   options cannot be mixed without intervening calls to the assembly
1674   routines.
1675 
1676   The grid coordinates are across the entire grid, not just the local portion
1677 
1678   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1679   as well as in C.
1680 
1681   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1682 
1683   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1684   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1685 
1686   The columns and rows in the stencil passed in MUST be contained within the
1687   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1688   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1689   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1690   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1691 
1692   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1693   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1694   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1695   `DM_BOUNDARY_PERIODIC` boundary type.
1696 
1697   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
1698   a single value per point) you can skip filling those indices.
1699 
1700   Inspired by the structured grid interface to the HYPRE package
1701   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1702 
1703   Efficiency Alert:
1704   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1705   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1706 
1707   Fortran Note:
1708   `idxm` and `idxn` should be declared as
1709 $     MatStencil idxm(4,m),idxn(4,n)
1710   and the values inserted using
1711 .vb
1712     idxm(MatStencil_i,1) = i
1713     idxm(MatStencil_j,1) = j
1714     idxm(MatStencil_k,1) = k
1715     idxm(MatStencil_c,1) = c
1716     etc
1717 .ve
1718 
1719 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1720           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1721 @*/
1722 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1723 {
1724   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1725   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1726   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1727 
1728   PetscFunctionBegin;
1729   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1731   PetscValidType(mat, 1);
1732   PetscAssertPointer(idxm, 3);
1733   PetscAssertPointer(idxn, 5);
1734 
1735   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1736     jdxm = buf;
1737     jdxn = buf + m;
1738   } else {
1739     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1740     jdxm = bufm;
1741     jdxn = bufn;
1742   }
1743   for (i = 0; i < m; i++) {
1744     for (j = 0; j < 3 - sdim; j++) dxm++;
1745     tmp = *dxm++ - starts[0];
1746     for (j = 0; j < dim - 1; j++) {
1747       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1748       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1749     }
1750     if (mat->stencil.noc) dxm++;
1751     jdxm[i] = tmp;
1752   }
1753   for (i = 0; i < n; i++) {
1754     for (j = 0; j < 3 - sdim; j++) dxn++;
1755     tmp = *dxn++ - starts[0];
1756     for (j = 0; j < dim - 1; j++) {
1757       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1758       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1759     }
1760     if (mat->stencil.noc) dxn++;
1761     jdxn[i] = tmp;
1762   }
1763   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1764   PetscCall(PetscFree2(bufm, bufn));
1765   PetscFunctionReturn(PETSC_SUCCESS);
1766 }
1767 
1768 /*@
1769   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1770   Using structured grid indexing
1771 
1772   Not Collective
1773 
1774   Input Parameters:
1775 + mat  - the matrix
1776 . m    - number of rows being entered
1777 . idxm - grid coordinates for matrix rows being entered
1778 . n    - number of columns being entered
1779 . idxn - grid coordinates for matrix columns being entered
1780 . v    - a logically two-dimensional array of values
1781 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1782 
1783   Level: beginner
1784 
1785   Notes:
1786   By default the values, `v`, are row-oriented and unsorted.
1787   See `MatSetOption()` for other options.
1788 
1789   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1790   options cannot be mixed without intervening calls to the assembly
1791   routines.
1792 
1793   The grid coordinates are across the entire grid, not just the local portion
1794 
1795   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1796   as well as in C.
1797 
1798   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1799 
1800   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1801   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1802 
1803   The columns and rows in the stencil passed in MUST be contained within the
1804   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1805   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1806   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1807   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1808 
1809   Negative indices may be passed in idxm and idxn, these rows and columns are
1810   simply ignored. This allows easily inserting element stiffness matrices
1811   with homogeneous Dirichlet boundary conditions that you don't want represented
1812   in the matrix.
1813 
1814   Inspired by the structured grid interface to the HYPRE package
1815   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1816 
1817   Fortran Note:
1818   `idxm` and `idxn` should be declared as
1819 $     MatStencil idxm(4,m),idxn(4,n)
1820   and the values inserted using
1821 .vb
1822     idxm(MatStencil_i,1) = i
1823     idxm(MatStencil_j,1) = j
1824     idxm(MatStencil_k,1) = k
1825    etc
1826 .ve
1827 
1828 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1829           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1830           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1831 @*/
1832 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1833 {
1834   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1835   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1836   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1837 
1838   PetscFunctionBegin;
1839   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1840   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1841   PetscValidType(mat, 1);
1842   PetscAssertPointer(idxm, 3);
1843   PetscAssertPointer(idxn, 5);
1844   PetscAssertPointer(v, 6);
1845 
1846   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1847     jdxm = buf;
1848     jdxn = buf + m;
1849   } else {
1850     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1851     jdxm = bufm;
1852     jdxn = bufn;
1853   }
1854   for (i = 0; i < m; i++) {
1855     for (j = 0; j < 3 - sdim; j++) dxm++;
1856     tmp = *dxm++ - starts[0];
1857     for (j = 0; j < sdim - 1; j++) {
1858       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1859       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1860     }
1861     dxm++;
1862     jdxm[i] = tmp;
1863   }
1864   for (i = 0; i < n; i++) {
1865     for (j = 0; j < 3 - sdim; j++) dxn++;
1866     tmp = *dxn++ - starts[0];
1867     for (j = 0; j < sdim - 1; j++) {
1868       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1869       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1870     }
1871     dxn++;
1872     jdxn[i] = tmp;
1873   }
1874   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1875   PetscCall(PetscFree2(bufm, bufn));
1876   PetscFunctionReturn(PETSC_SUCCESS);
1877 }
1878 
1879 /*@
1880   MatSetStencil - Sets the grid information for setting values into a matrix via
1881   `MatSetValuesStencil()`
1882 
1883   Not Collective
1884 
1885   Input Parameters:
1886 + mat    - the matrix
1887 . dim    - dimension of the grid 1, 2, or 3
1888 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1889 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1890 - dof    - number of degrees of freedom per node
1891 
1892   Level: beginner
1893 
1894   Notes:
1895   Inspired by the structured grid interface to the HYPRE package
1896   (www.llnl.gov/CASC/hyper)
1897 
1898   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1899   user.
1900 
1901 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1902           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1903 @*/
1904 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1905 {
1906   PetscFunctionBegin;
1907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1908   PetscAssertPointer(dims, 3);
1909   PetscAssertPointer(starts, 4);
1910 
1911   mat->stencil.dim = dim + (dof > 1);
1912   for (PetscInt i = 0; i < dim; i++) {
1913     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1914     mat->stencil.starts[i] = starts[dim - i - 1];
1915   }
1916   mat->stencil.dims[dim]   = dof;
1917   mat->stencil.starts[dim] = 0;
1918   mat->stencil.noc         = (PetscBool)(dof == 1);
1919   PetscFunctionReturn(PETSC_SUCCESS);
1920 }
1921 
1922 /*@C
1923   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1924 
1925   Not Collective
1926 
1927   Input Parameters:
1928 + mat  - the matrix
1929 . v    - a logically two-dimensional array of values
1930 . m    - the number of block rows
1931 . idxm - the global block indices
1932 . n    - the number of block columns
1933 . idxn - the global block indices
1934 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1935 
1936   Level: intermediate
1937 
1938   Notes:
1939   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1940   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1941 
1942   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1943   NOT the total number of rows/columns; for example, if the block size is 2 and
1944   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1945   The values in idxm would be 1 2; that is the first index for each block divided by
1946   the block size.
1947 
1948   You must call `MatSetBlockSize()` when constructing this matrix (before
1949   preallocating it).
1950 
1951   By default the values, `v`, are row-oriented, so the layout of
1952   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1953 
1954   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1955   options cannot be mixed without intervening calls to the assembly
1956   routines.
1957 
1958   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1959   as well as in C.
1960 
1961   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1962   simply ignored. This allows easily inserting element stiffness matrices
1963   with homogeneous Dirichlet boundary conditions that you don't want represented
1964   in the matrix.
1965 
1966   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1967   internal searching must be done to determine where to place the
1968   data in the matrix storage space.  By instead inserting blocks of
1969   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1970   reduced.
1971 
1972   Example:
1973 .vb
1974    Suppose m=n=2 and block size(bs) = 2 The array is
1975 
1976    1  2  | 3  4
1977    5  6  | 7  8
1978    - - - | - - -
1979    9  10 | 11 12
1980    13 14 | 15 16
1981 
1982    v[] should be passed in like
1983    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1984 
1985   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1986    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1987 .ve
1988 
1989 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1990 @*/
1991 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1992 {
1993   PetscFunctionBeginHot;
1994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1995   PetscValidType(mat, 1);
1996   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1997   PetscAssertPointer(idxm, 3);
1998   PetscAssertPointer(idxn, 5);
1999   MatCheckPreallocated(mat, 1);
2000   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2001   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2002   if (PetscDefined(USE_DEBUG)) {
2003     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2004     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2005   }
2006   if (PetscDefined(USE_DEBUG)) {
2007     PetscInt rbs, cbs, M, N, i;
2008     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2009     PetscCall(MatGetSize(mat, &M, &N));
2010     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);
2011     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);
2012   }
2013   if (mat->assembled) {
2014     mat->was_assembled = PETSC_TRUE;
2015     mat->assembled     = PETSC_FALSE;
2016   }
2017   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2018   if (mat->ops->setvaluesblocked) {
2019     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2020   } else {
2021     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2022     PetscInt i, j, bs, cbs;
2023 
2024     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2025     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2026       iidxm = buf;
2027       iidxn = buf + m * bs;
2028     } else {
2029       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2030       iidxm = bufr;
2031       iidxn = bufc;
2032     }
2033     for (i = 0; i < m; i++) {
2034       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2035     }
2036     if (m != n || bs != cbs || idxm != idxn) {
2037       for (i = 0; i < n; i++) {
2038         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2039       }
2040     } else iidxn = iidxm;
2041     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2042     PetscCall(PetscFree2(bufr, bufc));
2043   }
2044   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2045   PetscFunctionReturn(PETSC_SUCCESS);
2046 }
2047 
2048 /*@C
2049   MatGetValues - Gets a block of local values from a matrix.
2050 
2051   Not Collective; can only return values that are owned by the give process
2052 
2053   Input Parameters:
2054 + mat  - the matrix
2055 . v    - a logically two-dimensional array for storing the values
2056 . m    - the number of rows
2057 . idxm - the  global indices of the rows
2058 . n    - the number of columns
2059 - idxn - the global indices of the columns
2060 
2061   Level: advanced
2062 
2063   Notes:
2064   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2065   The values, `v`, are then returned in a row-oriented format,
2066   analogous to that used by default in `MatSetValues()`.
2067 
2068   `MatGetValues()` uses 0-based row and column numbers in
2069   Fortran as well as in C.
2070 
2071   `MatGetValues()` requires that the matrix has been assembled
2072   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2073   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2074   without intermediate matrix assembly.
2075 
2076   Negative row or column indices will be ignored and those locations in `v` will be
2077   left unchanged.
2078 
2079   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2080   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2081   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2082 
2083 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2084 @*/
2085 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2086 {
2087   PetscFunctionBegin;
2088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2089   PetscValidType(mat, 1);
2090   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2091   PetscAssertPointer(idxm, 3);
2092   PetscAssertPointer(idxn, 5);
2093   PetscAssertPointer(v, 6);
2094   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2095   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2096   MatCheckPreallocated(mat, 1);
2097 
2098   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2099   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2100   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2101   PetscFunctionReturn(PETSC_SUCCESS);
2102 }
2103 
2104 /*@C
2105   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2106   defined previously by `MatSetLocalToGlobalMapping()`
2107 
2108   Not Collective
2109 
2110   Input Parameters:
2111 + mat  - the matrix
2112 . nrow - number of rows
2113 . irow - the row local indices
2114 . ncol - number of columns
2115 - icol - the column local indices
2116 
2117   Output Parameter:
2118 . y - a logically two-dimensional array of values
2119 
2120   Level: advanced
2121 
2122   Notes:
2123   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2124 
2125   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,
2126   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2127   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2128   with `MatSetLocalToGlobalMapping()`.
2129 
2130   Developer Note:
2131   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2132   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2133 
2134 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2135           `MatSetValuesLocal()`, `MatGetValues()`
2136 @*/
2137 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2138 {
2139   PetscFunctionBeginHot;
2140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2141   PetscValidType(mat, 1);
2142   MatCheckPreallocated(mat, 1);
2143   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2144   PetscAssertPointer(irow, 3);
2145   PetscAssertPointer(icol, 5);
2146   if (PetscDefined(USE_DEBUG)) {
2147     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2148     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2149   }
2150   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2151   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2152   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2153   else {
2154     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2155     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2156       irowm = buf;
2157       icolm = buf + nrow;
2158     } else {
2159       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2160       irowm = bufr;
2161       icolm = bufc;
2162     }
2163     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2164     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2165     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2166     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2167     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2168     PetscCall(PetscFree2(bufr, bufc));
2169   }
2170   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2171   PetscFunctionReturn(PETSC_SUCCESS);
2172 }
2173 
2174 /*@
2175   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2176   the same size. Currently, this can only be called once and creates the given matrix.
2177 
2178   Not Collective
2179 
2180   Input Parameters:
2181 + mat  - the matrix
2182 . nb   - the number of blocks
2183 . bs   - the number of rows (and columns) in each block
2184 . rows - a concatenation of the rows for each block
2185 - v    - a concatenation of logically two-dimensional arrays of values
2186 
2187   Level: advanced
2188 
2189   Notes:
2190   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2191 
2192   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2193 
2194 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2195           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2196 @*/
2197 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2198 {
2199   PetscFunctionBegin;
2200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2201   PetscValidType(mat, 1);
2202   PetscAssertPointer(rows, 4);
2203   PetscAssertPointer(v, 5);
2204   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2205 
2206   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2207   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2208   else {
2209     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2210   }
2211   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2212   PetscFunctionReturn(PETSC_SUCCESS);
2213 }
2214 
2215 /*@
2216   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2217   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2218   using a local (per-processor) numbering.
2219 
2220   Not Collective
2221 
2222   Input Parameters:
2223 + x        - the matrix
2224 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2225 - cmapping - column mapping
2226 
2227   Level: intermediate
2228 
2229   Note:
2230   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2231 
2232 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2233 @*/
2234 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2235 {
2236   PetscFunctionBegin;
2237   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2238   PetscValidType(x, 1);
2239   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2240   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2241   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2242   else {
2243     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2244     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2245   }
2246   PetscFunctionReturn(PETSC_SUCCESS);
2247 }
2248 
2249 /*@
2250   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2251 
2252   Not Collective
2253 
2254   Input Parameter:
2255 . A - the matrix
2256 
2257   Output Parameters:
2258 + rmapping - row mapping
2259 - cmapping - column mapping
2260 
2261   Level: advanced
2262 
2263 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2264 @*/
2265 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2269   PetscValidType(A, 1);
2270   if (rmapping) {
2271     PetscAssertPointer(rmapping, 2);
2272     *rmapping = A->rmap->mapping;
2273   }
2274   if (cmapping) {
2275     PetscAssertPointer(cmapping, 3);
2276     *cmapping = A->cmap->mapping;
2277   }
2278   PetscFunctionReturn(PETSC_SUCCESS);
2279 }
2280 
2281 /*@
2282   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2283 
2284   Logically Collective
2285 
2286   Input Parameters:
2287 + A    - the matrix
2288 . rmap - row layout
2289 - cmap - column layout
2290 
2291   Level: advanced
2292 
2293   Note:
2294   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2295 
2296 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2297 @*/
2298 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2299 {
2300   PetscFunctionBegin;
2301   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2302   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2303   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@
2308   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2309 
2310   Not Collective
2311 
2312   Input Parameter:
2313 . A - the matrix
2314 
2315   Output Parameters:
2316 + rmap - row layout
2317 - cmap - column layout
2318 
2319   Level: advanced
2320 
2321 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2322 @*/
2323 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2324 {
2325   PetscFunctionBegin;
2326   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2327   PetscValidType(A, 1);
2328   if (rmap) {
2329     PetscAssertPointer(rmap, 2);
2330     *rmap = A->rmap;
2331   }
2332   if (cmap) {
2333     PetscAssertPointer(cmap, 3);
2334     *cmap = A->cmap;
2335   }
2336   PetscFunctionReturn(PETSC_SUCCESS);
2337 }
2338 
2339 /*@C
2340   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2341   using a local numbering of the rows and columns.
2342 
2343   Not Collective
2344 
2345   Input Parameters:
2346 + mat  - the matrix
2347 . nrow - number of rows
2348 . irow - the row local indices
2349 . ncol - number of columns
2350 . icol - the column local indices
2351 . y    - a logically two-dimensional array of values
2352 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2353 
2354   Level: intermediate
2355 
2356   Notes:
2357   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2358 
2359   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2360   options cannot be mixed without intervening calls to the assembly
2361   routines.
2362 
2363   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2364   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2365 
2366   Developer Note:
2367   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2368   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2369 
2370 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2371           `MatGetValuesLocal()`
2372 @*/
2373 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2374 {
2375   PetscFunctionBeginHot;
2376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2377   PetscValidType(mat, 1);
2378   MatCheckPreallocated(mat, 1);
2379   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2380   PetscAssertPointer(irow, 3);
2381   PetscAssertPointer(icol, 5);
2382   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2383   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2384   if (PetscDefined(USE_DEBUG)) {
2385     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2386     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2387   }
2388 
2389   if (mat->assembled) {
2390     mat->was_assembled = PETSC_TRUE;
2391     mat->assembled     = PETSC_FALSE;
2392   }
2393   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2394   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2395   else {
2396     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2397     const PetscInt *irowm, *icolm;
2398 
2399     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2400       bufr  = buf;
2401       bufc  = buf + nrow;
2402       irowm = bufr;
2403       icolm = bufc;
2404     } else {
2405       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2406       irowm = bufr;
2407       icolm = bufc;
2408     }
2409     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2410     else irowm = irow;
2411     if (mat->cmap->mapping) {
2412       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2413         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2414       } else icolm = irowm;
2415     } else icolm = icol;
2416     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2417     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2418   }
2419   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2420   PetscFunctionReturn(PETSC_SUCCESS);
2421 }
2422 
2423 /*@C
2424   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2425   using a local ordering of the nodes a block at a time.
2426 
2427   Not Collective
2428 
2429   Input Parameters:
2430 + mat  - the matrix
2431 . nrow - number of rows
2432 . irow - the row local indices
2433 . ncol - number of columns
2434 . icol - the column local indices
2435 . y    - a logically two-dimensional array of values
2436 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2437 
2438   Level: intermediate
2439 
2440   Notes:
2441   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2442   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2443 
2444   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2445   options cannot be mixed without intervening calls to the assembly
2446   routines.
2447 
2448   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2449   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2450 
2451   Developer Note:
2452   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2453   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2454 
2455 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2456           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2457 @*/
2458 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2459 {
2460   PetscFunctionBeginHot;
2461   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2462   PetscValidType(mat, 1);
2463   MatCheckPreallocated(mat, 1);
2464   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2465   PetscAssertPointer(irow, 3);
2466   PetscAssertPointer(icol, 5);
2467   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2468   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2469   if (PetscDefined(USE_DEBUG)) {
2470     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2471     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);
2472   }
2473 
2474   if (mat->assembled) {
2475     mat->was_assembled = PETSC_TRUE;
2476     mat->assembled     = PETSC_FALSE;
2477   }
2478   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2479     PetscInt irbs, rbs;
2480     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2481     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2482     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2483   }
2484   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2485     PetscInt icbs, cbs;
2486     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2487     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2488     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2489   }
2490   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2491   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2492   else {
2493     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2494     const PetscInt *irowm, *icolm;
2495 
2496     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2497       bufr  = buf;
2498       bufc  = buf + nrow;
2499       irowm = bufr;
2500       icolm = bufc;
2501     } else {
2502       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2503       irowm = bufr;
2504       icolm = bufc;
2505     }
2506     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2507     else irowm = irow;
2508     if (mat->cmap->mapping) {
2509       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2510         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2511       } else icolm = irowm;
2512     } else icolm = icol;
2513     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2514     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2515   }
2516   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2517   PetscFunctionReturn(PETSC_SUCCESS);
2518 }
2519 
2520 /*@
2521   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2522 
2523   Collective
2524 
2525   Input Parameters:
2526 + mat - the matrix
2527 - x   - the vector to be multiplied
2528 
2529   Output Parameter:
2530 . y - the result
2531 
2532   Level: developer
2533 
2534   Note:
2535   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2536   call `MatMultDiagonalBlock`(A,y,y).
2537 
2538 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2539 @*/
2540 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2541 {
2542   PetscFunctionBegin;
2543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2544   PetscValidType(mat, 1);
2545   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2546   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2547 
2548   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2549   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2550   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2551   MatCheckPreallocated(mat, 1);
2552 
2553   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2554   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2555   PetscFunctionReturn(PETSC_SUCCESS);
2556 }
2557 
2558 /*@
2559   MatMult - Computes the matrix-vector product, $y = Ax$.
2560 
2561   Neighbor-wise Collective
2562 
2563   Input Parameters:
2564 + mat - the matrix
2565 - x   - the vector to be multiplied
2566 
2567   Output Parameter:
2568 . y - the result
2569 
2570   Level: beginner
2571 
2572   Note:
2573   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2574   call `MatMult`(A,y,y).
2575 
2576 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2577 @*/
2578 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2579 {
2580   PetscFunctionBegin;
2581   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2582   PetscValidType(mat, 1);
2583   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2584   VecCheckAssembled(x);
2585   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2586   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2587   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2588   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2589   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);
2590   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);
2591   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);
2592   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);
2593   PetscCall(VecSetErrorIfLocked(y, 3));
2594   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2595   MatCheckPreallocated(mat, 1);
2596 
2597   PetscCall(VecLockReadPush(x));
2598   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2599   PetscUseTypeMethod(mat, mult, x, y);
2600   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2601   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2602   PetscCall(VecLockReadPop(x));
2603   PetscFunctionReturn(PETSC_SUCCESS);
2604 }
2605 
2606 /*@
2607   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2608 
2609   Neighbor-wise Collective
2610 
2611   Input Parameters:
2612 + mat - the matrix
2613 - x   - the vector to be multiplied
2614 
2615   Output Parameter:
2616 . y - the result
2617 
2618   Level: beginner
2619 
2620   Notes:
2621   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2622   call `MatMultTranspose`(A,y,y).
2623 
2624   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2625   use `MatMultHermitianTranspose()`
2626 
2627 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2628 @*/
2629 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2630 {
2631   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2632 
2633   PetscFunctionBegin;
2634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2635   PetscValidType(mat, 1);
2636   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2637   VecCheckAssembled(x);
2638   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2639 
2640   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2641   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2642   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2643   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);
2644   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);
2645   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);
2646   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);
2647   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2648   MatCheckPreallocated(mat, 1);
2649 
2650   if (!mat->ops->multtranspose) {
2651     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2652     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);
2653   } else op = mat->ops->multtranspose;
2654   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2655   PetscCall(VecLockReadPush(x));
2656   PetscCall((*op)(mat, x, y));
2657   PetscCall(VecLockReadPop(x));
2658   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2659   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2660   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2661   PetscFunctionReturn(PETSC_SUCCESS);
2662 }
2663 
2664 /*@
2665   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2666 
2667   Neighbor-wise Collective
2668 
2669   Input Parameters:
2670 + mat - the matrix
2671 - x   - the vector to be multiplied
2672 
2673   Output Parameter:
2674 . y - the result
2675 
2676   Level: beginner
2677 
2678   Notes:
2679   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2680   call `MatMultHermitianTranspose`(A,y,y).
2681 
2682   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2683 
2684   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2685 
2686 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2687 @*/
2688 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2689 {
2690   PetscFunctionBegin;
2691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2692   PetscValidType(mat, 1);
2693   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2694   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2695 
2696   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2697   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2698   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2699   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);
2700   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);
2701   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);
2702   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);
2703   MatCheckPreallocated(mat, 1);
2704 
2705   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2706 #if defined(PETSC_USE_COMPLEX)
2707   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2708     PetscCall(VecLockReadPush(x));
2709     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2710     else PetscUseTypeMethod(mat, mult, x, y);
2711     PetscCall(VecLockReadPop(x));
2712   } else {
2713     Vec w;
2714     PetscCall(VecDuplicate(x, &w));
2715     PetscCall(VecCopy(x, w));
2716     PetscCall(VecConjugate(w));
2717     PetscCall(MatMultTranspose(mat, w, y));
2718     PetscCall(VecDestroy(&w));
2719     PetscCall(VecConjugate(y));
2720   }
2721   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2722 #else
2723   PetscCall(MatMultTranspose(mat, x, y));
2724 #endif
2725   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2726   PetscFunctionReturn(PETSC_SUCCESS);
2727 }
2728 
2729 /*@
2730   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2731 
2732   Neighbor-wise Collective
2733 
2734   Input Parameters:
2735 + mat - the matrix
2736 . v1  - the vector to be multiplied by `mat`
2737 - v2  - the vector to be added to the result
2738 
2739   Output Parameter:
2740 . v3 - the result
2741 
2742   Level: beginner
2743 
2744   Note:
2745   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2746   call `MatMultAdd`(A,v1,v2,v1).
2747 
2748 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2749 @*/
2750 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2751 {
2752   PetscFunctionBegin;
2753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2754   PetscValidType(mat, 1);
2755   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2756   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2757   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2758 
2759   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2760   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2761   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);
2762   /* 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);
2763      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); */
2764   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);
2765   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);
2766   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2767   MatCheckPreallocated(mat, 1);
2768 
2769   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2770   PetscCall(VecLockReadPush(v1));
2771   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2772   PetscCall(VecLockReadPop(v1));
2773   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2774   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2775   PetscFunctionReturn(PETSC_SUCCESS);
2776 }
2777 
2778 /*@
2779   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2780 
2781   Neighbor-wise Collective
2782 
2783   Input Parameters:
2784 + mat - the matrix
2785 . v1  - the vector to be multiplied by the transpose of the matrix
2786 - v2  - the vector to be added to the result
2787 
2788   Output Parameter:
2789 . v3 - the result
2790 
2791   Level: beginner
2792 
2793   Note:
2794   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2795   call `MatMultTransposeAdd`(A,v1,v2,v1).
2796 
2797 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2798 @*/
2799 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2800 {
2801   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2802 
2803   PetscFunctionBegin;
2804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2805   PetscValidType(mat, 1);
2806   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2807   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2808   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2809 
2810   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2811   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2812   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);
2813   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);
2814   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);
2815   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2816   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2817   MatCheckPreallocated(mat, 1);
2818 
2819   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2820   PetscCall(VecLockReadPush(v1));
2821   PetscCall((*op)(mat, v1, v2, v3));
2822   PetscCall(VecLockReadPop(v1));
2823   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2824   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2825   PetscFunctionReturn(PETSC_SUCCESS);
2826 }
2827 
2828 /*@
2829   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2830 
2831   Neighbor-wise Collective
2832 
2833   Input Parameters:
2834 + mat - the matrix
2835 . v1  - the vector to be multiplied by the Hermitian transpose
2836 - v2  - the vector to be added to the result
2837 
2838   Output Parameter:
2839 . v3 - the result
2840 
2841   Level: beginner
2842 
2843   Note:
2844   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2845   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2846 
2847 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2848 @*/
2849 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2850 {
2851   PetscFunctionBegin;
2852   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2853   PetscValidType(mat, 1);
2854   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2855   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2856   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2857 
2858   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2859   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2860   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2861   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);
2862   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);
2863   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);
2864   MatCheckPreallocated(mat, 1);
2865 
2866   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2867   PetscCall(VecLockReadPush(v1));
2868   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2869   else {
2870     Vec w, z;
2871     PetscCall(VecDuplicate(v1, &w));
2872     PetscCall(VecCopy(v1, w));
2873     PetscCall(VecConjugate(w));
2874     PetscCall(VecDuplicate(v3, &z));
2875     PetscCall(MatMultTranspose(mat, w, z));
2876     PetscCall(VecDestroy(&w));
2877     PetscCall(VecConjugate(z));
2878     if (v2 != v3) {
2879       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2880     } else {
2881       PetscCall(VecAXPY(v3, 1.0, z));
2882     }
2883     PetscCall(VecDestroy(&z));
2884   }
2885   PetscCall(VecLockReadPop(v1));
2886   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2887   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2888   PetscFunctionReturn(PETSC_SUCCESS);
2889 }
2890 
2891 /*@C
2892   MatGetFactorType - gets the type of factorization a matrix is
2893 
2894   Not Collective
2895 
2896   Input Parameter:
2897 . mat - the matrix
2898 
2899   Output Parameter:
2900 . 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`
2901 
2902   Level: intermediate
2903 
2904 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2905           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2906 @*/
2907 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2908 {
2909   PetscFunctionBegin;
2910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2911   PetscValidType(mat, 1);
2912   PetscAssertPointer(t, 2);
2913   *t = mat->factortype;
2914   PetscFunctionReturn(PETSC_SUCCESS);
2915 }
2916 
2917 /*@C
2918   MatSetFactorType - sets the type of factorization a matrix is
2919 
2920   Logically Collective
2921 
2922   Input Parameters:
2923 + mat - the matrix
2924 - 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`
2925 
2926   Level: intermediate
2927 
2928 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2929           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2930 @*/
2931 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2932 {
2933   PetscFunctionBegin;
2934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2935   PetscValidType(mat, 1);
2936   mat->factortype = t;
2937   PetscFunctionReturn(PETSC_SUCCESS);
2938 }
2939 
2940 /*@C
2941   MatGetInfo - Returns information about matrix storage (number of
2942   nonzeros, memory, etc.).
2943 
2944   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2945 
2946   Input Parameters:
2947 + mat  - the matrix
2948 - 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)
2949 
2950   Output Parameter:
2951 . info - matrix information context
2952 
2953   Options Database Key:
2954 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2955 
2956   Notes:
2957   The `MatInfo` context contains a variety of matrix data, including
2958   number of nonzeros allocated and used, number of mallocs during
2959   matrix assembly, etc.  Additional information for factored matrices
2960   is provided (such as the fill ratio, number of mallocs during
2961   factorization, etc.).
2962 
2963   Example:
2964   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2965   data within the MatInfo context.  For example,
2966 .vb
2967       MatInfo info;
2968       Mat     A;
2969       double  mal, nz_a, nz_u;
2970 
2971       MatGetInfo(A, MAT_LOCAL, &info);
2972       mal  = info.mallocs;
2973       nz_a = info.nz_allocated;
2974 .ve
2975 
2976   Fortran users should declare info as a double precision
2977   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2978   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2979   a complete list of parameter names.
2980 .vb
2981       double  precision info(MAT_INFO_SIZE)
2982       double  precision mal, nz_a
2983       Mat     A
2984       integer ierr
2985 
2986       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2987       mal = info(MAT_INFO_MALLOCS)
2988       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2989 .ve
2990 
2991   Level: intermediate
2992 
2993   Developer Note:
2994   The Fortran interface is not autogenerated as the
2995   interface definition cannot be generated correctly [due to `MatInfo` argument]
2996 
2997 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2998 @*/
2999 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3000 {
3001   PetscFunctionBegin;
3002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3003   PetscValidType(mat, 1);
3004   PetscAssertPointer(info, 3);
3005   MatCheckPreallocated(mat, 1);
3006   PetscUseTypeMethod(mat, getinfo, flag, info);
3007   PetscFunctionReturn(PETSC_SUCCESS);
3008 }
3009 
3010 /*
3011    This is used by external packages where it is not easy to get the info from the actual
3012    matrix factorization.
3013 */
3014 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3015 {
3016   PetscFunctionBegin;
3017   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3018   PetscFunctionReturn(PETSC_SUCCESS);
3019 }
3020 
3021 /*@C
3022   MatLUFactor - Performs in-place LU factorization of matrix.
3023 
3024   Collective
3025 
3026   Input Parameters:
3027 + mat  - the matrix
3028 . row  - row permutation
3029 . col  - column permutation
3030 - info - options for factorization, includes
3031 .vb
3032           fill - expected fill as ratio of original fill.
3033           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3034                    Run with the option -info to determine an optimal value to use
3035 .ve
3036 
3037   Level: developer
3038 
3039   Notes:
3040   Most users should employ the `KSP` interface for linear solvers
3041   instead of working directly with matrix algebra routines such as this.
3042   See, e.g., `KSPCreate()`.
3043 
3044   This changes the state of the matrix to a factored matrix; it cannot be used
3045   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3046 
3047   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3048   when not using `KSP`.
3049 
3050   Developer Note:
3051   The Fortran interface is not autogenerated as the
3052   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3053 
3054 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3055           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3056 @*/
3057 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3058 {
3059   MatFactorInfo tinfo;
3060 
3061   PetscFunctionBegin;
3062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3063   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3064   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3065   if (info) PetscAssertPointer(info, 4);
3066   PetscValidType(mat, 1);
3067   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3068   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3069   MatCheckPreallocated(mat, 1);
3070   if (!info) {
3071     PetscCall(MatFactorInfoInitialize(&tinfo));
3072     info = &tinfo;
3073   }
3074 
3075   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3076   PetscUseTypeMethod(mat, lufactor, row, col, info);
3077   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3078   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3079   PetscFunctionReturn(PETSC_SUCCESS);
3080 }
3081 
3082 /*@C
3083   MatILUFactor - Performs in-place ILU factorization of matrix.
3084 
3085   Collective
3086 
3087   Input Parameters:
3088 + mat  - the matrix
3089 . row  - row permutation
3090 . col  - column permutation
3091 - info - structure containing
3092 .vb
3093       levels - number of levels of fill.
3094       expected fill - as ratio of original fill.
3095       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3096                 missing diagonal entries)
3097 .ve
3098 
3099   Level: developer
3100 
3101   Notes:
3102   Most users should employ the `KSP` interface for linear solvers
3103   instead of working directly with matrix algebra routines such as this.
3104   See, e.g., `KSPCreate()`.
3105 
3106   Probably really in-place only when level of fill is zero, otherwise allocates
3107   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3108   when not using `KSP`.
3109 
3110   Developer Note:
3111   The Fortran interface is not autogenerated as the
3112   interface definition cannot be generated correctly [due to MatFactorInfo]
3113 
3114 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3115 @*/
3116 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3117 {
3118   PetscFunctionBegin;
3119   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3120   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3121   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3122   PetscAssertPointer(info, 4);
3123   PetscValidType(mat, 1);
3124   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3125   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3126   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3127   MatCheckPreallocated(mat, 1);
3128 
3129   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3130   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3131   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3132   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3133   PetscFunctionReturn(PETSC_SUCCESS);
3134 }
3135 
3136 /*@C
3137   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3138   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3139 
3140   Collective
3141 
3142   Input Parameters:
3143 + fact - the factor matrix obtained with `MatGetFactor()`
3144 . mat  - the matrix
3145 . row  - the row permutation
3146 . col  - the column permutation
3147 - info - options for factorization, includes
3148 .vb
3149           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3150           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3151 .ve
3152 
3153   Level: developer
3154 
3155   Notes:
3156   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3157 
3158   Most users should employ the simplified `KSP` interface for linear solvers
3159   instead of working directly with matrix algebra routines such as this.
3160   See, e.g., `KSPCreate()`.
3161 
3162   Developer Note:
3163   The Fortran interface is not autogenerated as the
3164   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3165 
3166 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3167 @*/
3168 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3169 {
3170   MatFactorInfo tinfo;
3171 
3172   PetscFunctionBegin;
3173   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3175   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3176   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3177   if (info) PetscAssertPointer(info, 5);
3178   PetscValidType(fact, 1);
3179   PetscValidType(mat, 2);
3180   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3181   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3182   MatCheckPreallocated(mat, 2);
3183   if (!info) {
3184     PetscCall(MatFactorInfoInitialize(&tinfo));
3185     info = &tinfo;
3186   }
3187 
3188   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3189   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3190   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3191   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3192   PetscFunctionReturn(PETSC_SUCCESS);
3193 }
3194 
3195 /*@C
3196   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3197   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3198 
3199   Collective
3200 
3201   Input Parameters:
3202 + fact - the factor matrix obtained with `MatGetFactor()`
3203 . mat  - the matrix
3204 - info - options for factorization
3205 
3206   Level: developer
3207 
3208   Notes:
3209   See `MatLUFactor()` for in-place factorization.  See
3210   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3211 
3212   Most users should employ the `KSP` interface for linear solvers
3213   instead of working directly with matrix algebra routines such as this.
3214   See, e.g., `KSPCreate()`.
3215 
3216   Developer Note:
3217   The Fortran interface is not autogenerated as the
3218   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3219 
3220 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3221 @*/
3222 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3223 {
3224   MatFactorInfo tinfo;
3225 
3226   PetscFunctionBegin;
3227   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3228   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3229   PetscValidType(fact, 1);
3230   PetscValidType(mat, 2);
3231   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3232   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,
3233              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3234 
3235   MatCheckPreallocated(mat, 2);
3236   if (!info) {
3237     PetscCall(MatFactorInfoInitialize(&tinfo));
3238     info = &tinfo;
3239   }
3240 
3241   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3242   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3243   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3244   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3245   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3246   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3247   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3248   PetscFunctionReturn(PETSC_SUCCESS);
3249 }
3250 
3251 /*@C
3252   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3253   symmetric matrix.
3254 
3255   Collective
3256 
3257   Input Parameters:
3258 + mat  - the matrix
3259 . perm - row and column permutations
3260 - info - expected fill as ratio of original fill
3261 
3262   Level: developer
3263 
3264   Notes:
3265   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3266   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3267 
3268   Most users should employ the `KSP` interface for linear solvers
3269   instead of working directly with matrix algebra routines such as this.
3270   See, e.g., `KSPCreate()`.
3271 
3272   Developer Note:
3273   The Fortran interface is not autogenerated as the
3274   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3275 
3276 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3277           `MatGetOrdering()`
3278 @*/
3279 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3280 {
3281   MatFactorInfo tinfo;
3282 
3283   PetscFunctionBegin;
3284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3285   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3286   if (info) PetscAssertPointer(info, 3);
3287   PetscValidType(mat, 1);
3288   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3289   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3290   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3291   MatCheckPreallocated(mat, 1);
3292   if (!info) {
3293     PetscCall(MatFactorInfoInitialize(&tinfo));
3294     info = &tinfo;
3295   }
3296 
3297   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3298   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3299   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3300   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3301   PetscFunctionReturn(PETSC_SUCCESS);
3302 }
3303 
3304 /*@C
3305   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3306   of a symmetric matrix.
3307 
3308   Collective
3309 
3310   Input Parameters:
3311 + fact - the factor matrix obtained with `MatGetFactor()`
3312 . mat  - the matrix
3313 . perm - row and column permutations
3314 - info - options for factorization, includes
3315 .vb
3316           fill - expected fill as ratio of original fill.
3317           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3318                    Run with the option -info to determine an optimal value to use
3319 .ve
3320 
3321   Level: developer
3322 
3323   Notes:
3324   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3325   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3326 
3327   Most users should employ the `KSP` interface for linear solvers
3328   instead of working directly with matrix algebra routines such as this.
3329   See, e.g., `KSPCreate()`.
3330 
3331   Developer Note:
3332   The Fortran interface is not autogenerated as the
3333   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3334 
3335 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3336           `MatGetOrdering()`
3337 @*/
3338 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3339 {
3340   MatFactorInfo tinfo;
3341 
3342   PetscFunctionBegin;
3343   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3344   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3345   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3346   if (info) PetscAssertPointer(info, 4);
3347   PetscValidType(fact, 1);
3348   PetscValidType(mat, 2);
3349   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3350   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3351   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3352   MatCheckPreallocated(mat, 2);
3353   if (!info) {
3354     PetscCall(MatFactorInfoInitialize(&tinfo));
3355     info = &tinfo;
3356   }
3357 
3358   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3359   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3360   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3361   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3362   PetscFunctionReturn(PETSC_SUCCESS);
3363 }
3364 
3365 /*@C
3366   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3367   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3368   `MatCholeskyFactorSymbolic()`.
3369 
3370   Collective
3371 
3372   Input Parameters:
3373 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3374 . mat  - the initial matrix that is to be factored
3375 - info - options for factorization
3376 
3377   Level: developer
3378 
3379   Note:
3380   Most users should employ the `KSP` interface for linear solvers
3381   instead of working directly with matrix algebra routines such as this.
3382   See, e.g., `KSPCreate()`.
3383 
3384   Developer Note:
3385   The Fortran interface is not autogenerated as the
3386   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3387 
3388 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3389 @*/
3390 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3391 {
3392   MatFactorInfo tinfo;
3393 
3394   PetscFunctionBegin;
3395   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3397   PetscValidType(fact, 1);
3398   PetscValidType(mat, 2);
3399   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3400   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,
3401              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3402   MatCheckPreallocated(mat, 2);
3403   if (!info) {
3404     PetscCall(MatFactorInfoInitialize(&tinfo));
3405     info = &tinfo;
3406   }
3407 
3408   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3409   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3410   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3411   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3412   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3413   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3414   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3415   PetscFunctionReturn(PETSC_SUCCESS);
3416 }
3417 
3418 /*@
3419   MatQRFactor - Performs in-place QR factorization of matrix.
3420 
3421   Collective
3422 
3423   Input Parameters:
3424 + mat  - the matrix
3425 . col  - column permutation
3426 - info - options for factorization, includes
3427 .vb
3428           fill - expected fill as ratio of original fill.
3429           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3430                    Run with the option -info to determine an optimal value to use
3431 .ve
3432 
3433   Level: developer
3434 
3435   Notes:
3436   Most users should employ the `KSP` interface for linear solvers
3437   instead of working directly with matrix algebra routines such as this.
3438   See, e.g., `KSPCreate()`.
3439 
3440   This changes the state of the matrix to a factored matrix; it cannot be used
3441   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3442 
3443   Developer Note:
3444   The Fortran interface is not autogenerated as the
3445   interface definition cannot be generated correctly [due to MatFactorInfo]
3446 
3447 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3448           `MatSetUnfactored()`
3449 @*/
3450 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3451 {
3452   PetscFunctionBegin;
3453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3454   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3455   if (info) PetscAssertPointer(info, 3);
3456   PetscValidType(mat, 1);
3457   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3458   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3459   MatCheckPreallocated(mat, 1);
3460   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3461   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3462   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3463   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3464   PetscFunctionReturn(PETSC_SUCCESS);
3465 }
3466 
3467 /*@
3468   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3469   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3470 
3471   Collective
3472 
3473   Input Parameters:
3474 + fact - the factor matrix obtained with `MatGetFactor()`
3475 . mat  - the matrix
3476 . col  - column permutation
3477 - info - options for factorization, includes
3478 .vb
3479           fill - expected fill as ratio of original fill.
3480           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3481                    Run with the option -info to determine an optimal value to use
3482 .ve
3483 
3484   Level: developer
3485 
3486   Note:
3487   Most users should employ the `KSP` interface for linear solvers
3488   instead of working directly with matrix algebra routines such as this.
3489   See, e.g., `KSPCreate()`.
3490 
3491   Developer Note:
3492   The Fortran interface is not autogenerated as the
3493   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3494 
3495 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3496 @*/
3497 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3498 {
3499   MatFactorInfo tinfo;
3500 
3501   PetscFunctionBegin;
3502   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3504   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3505   if (info) PetscAssertPointer(info, 4);
3506   PetscValidType(fact, 1);
3507   PetscValidType(mat, 2);
3508   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3509   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3510   MatCheckPreallocated(mat, 2);
3511   if (!info) {
3512     PetscCall(MatFactorInfoInitialize(&tinfo));
3513     info = &tinfo;
3514   }
3515 
3516   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3517   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3518   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3519   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3520   PetscFunctionReturn(PETSC_SUCCESS);
3521 }
3522 
3523 /*@
3524   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3525   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3526 
3527   Collective
3528 
3529   Input Parameters:
3530 + fact - the factor matrix obtained with `MatGetFactor()`
3531 . mat  - the matrix
3532 - info - options for factorization
3533 
3534   Level: developer
3535 
3536   Notes:
3537   See `MatQRFactor()` for in-place factorization.
3538 
3539   Most users should employ the `KSP` interface for linear solvers
3540   instead of working directly with matrix algebra routines such as this.
3541   See, e.g., `KSPCreate()`.
3542 
3543   Developer Note:
3544   The Fortran interface is not autogenerated as the
3545   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3546 
3547 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3548 @*/
3549 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3550 {
3551   MatFactorInfo tinfo;
3552 
3553   PetscFunctionBegin;
3554   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3556   PetscValidType(fact, 1);
3557   PetscValidType(mat, 2);
3558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3559   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,
3560              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3561 
3562   MatCheckPreallocated(mat, 2);
3563   if (!info) {
3564     PetscCall(MatFactorInfoInitialize(&tinfo));
3565     info = &tinfo;
3566   }
3567 
3568   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3569   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3570   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3571   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3572   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3573   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3574   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3575   PetscFunctionReturn(PETSC_SUCCESS);
3576 }
3577 
3578 /*@
3579   MatSolve - Solves $A x = b$, given a factored matrix.
3580 
3581   Neighbor-wise Collective
3582 
3583   Input Parameters:
3584 + mat - the factored matrix
3585 - b   - the right-hand-side vector
3586 
3587   Output Parameter:
3588 . x - the result vector
3589 
3590   Level: developer
3591 
3592   Notes:
3593   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3594   call `MatSolve`(A,x,x).
3595 
3596   Most users should employ the `KSP` interface for linear solvers
3597   instead of working directly with matrix algebra routines such as this.
3598   See, e.g., `KSPCreate()`.
3599 
3600 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3601 @*/
3602 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3603 {
3604   PetscFunctionBegin;
3605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3606   PetscValidType(mat, 1);
3607   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3608   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3609   PetscCheckSameComm(mat, 1, b, 2);
3610   PetscCheckSameComm(mat, 1, x, 3);
3611   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3612   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);
3613   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);
3614   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);
3615   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3616   MatCheckPreallocated(mat, 1);
3617 
3618   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3619   if (mat->factorerrortype) {
3620     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3621     PetscCall(VecSetInf(x));
3622   } else PetscUseTypeMethod(mat, solve, b, x);
3623   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3624   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3625   PetscFunctionReturn(PETSC_SUCCESS);
3626 }
3627 
3628 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3629 {
3630   Vec      b, x;
3631   PetscInt N, i;
3632   PetscErrorCode (*f)(Mat, Vec, Vec);
3633   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3634 
3635   PetscFunctionBegin;
3636   if (A->factorerrortype) {
3637     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3638     PetscCall(MatSetInf(X));
3639     PetscFunctionReturn(PETSC_SUCCESS);
3640   }
3641   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3642   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3643   PetscCall(MatBoundToCPU(A, &Abound));
3644   if (!Abound) {
3645     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3646     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3647   }
3648 #if PetscDefined(HAVE_CUDA)
3649   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3650   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3651 #elif PetscDefined(HAVE_HIP)
3652   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3653   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3654 #endif
3655   PetscCall(MatGetSize(B, NULL, &N));
3656   for (i = 0; i < N; i++) {
3657     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3658     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3659     PetscCall((*f)(A, b, x));
3660     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3661     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3662   }
3663   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3664   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3665   PetscFunctionReturn(PETSC_SUCCESS);
3666 }
3667 
3668 /*@
3669   MatMatSolve - Solves $A X = B$, given a factored matrix.
3670 
3671   Neighbor-wise Collective
3672 
3673   Input Parameters:
3674 + A - the factored matrix
3675 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3676 
3677   Output Parameter:
3678 . X - the result matrix (dense matrix)
3679 
3680   Level: developer
3681 
3682   Note:
3683   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3684   otherwise, `B` and `X` cannot be the same.
3685 
3686 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3687 @*/
3688 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3689 {
3690   PetscFunctionBegin;
3691   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3692   PetscValidType(A, 1);
3693   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3694   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3695   PetscCheckSameComm(A, 1, B, 2);
3696   PetscCheckSameComm(A, 1, X, 3);
3697   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);
3698   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);
3699   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");
3700   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3701   MatCheckPreallocated(A, 1);
3702 
3703   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3704   if (!A->ops->matsolve) {
3705     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3706     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3707   } else PetscUseTypeMethod(A, matsolve, B, X);
3708   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3709   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3710   PetscFunctionReturn(PETSC_SUCCESS);
3711 }
3712 
3713 /*@
3714   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3715 
3716   Neighbor-wise Collective
3717 
3718   Input Parameters:
3719 + A - the factored matrix
3720 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3721 
3722   Output Parameter:
3723 . X - the result matrix (dense matrix)
3724 
3725   Level: developer
3726 
3727   Note:
3728   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3729   call `MatMatSolveTranspose`(A,X,X).
3730 
3731 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3732 @*/
3733 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3734 {
3735   PetscFunctionBegin;
3736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3737   PetscValidType(A, 1);
3738   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3739   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3740   PetscCheckSameComm(A, 1, B, 2);
3741   PetscCheckSameComm(A, 1, X, 3);
3742   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3743   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);
3744   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);
3745   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);
3746   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");
3747   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3748   MatCheckPreallocated(A, 1);
3749 
3750   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3751   if (!A->ops->matsolvetranspose) {
3752     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3753     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3754   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3755   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3756   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3757   PetscFunctionReturn(PETSC_SUCCESS);
3758 }
3759 
3760 /*@
3761   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3762 
3763   Neighbor-wise Collective
3764 
3765   Input Parameters:
3766 + A  - the factored matrix
3767 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3768 
3769   Output Parameter:
3770 . X - the result matrix (dense matrix)
3771 
3772   Level: developer
3773 
3774   Note:
3775   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create `Bt` in sparse compressed row
3776   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3777 
3778 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3779 @*/
3780 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3781 {
3782   PetscFunctionBegin;
3783   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3784   PetscValidType(A, 1);
3785   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3786   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3787   PetscCheckSameComm(A, 1, Bt, 2);
3788   PetscCheckSameComm(A, 1, X, 3);
3789 
3790   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3791   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);
3792   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);
3793   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");
3794   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3795   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3796   MatCheckPreallocated(A, 1);
3797 
3798   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3799   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3800   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3801   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3802   PetscFunctionReturn(PETSC_SUCCESS);
3803 }
3804 
3805 /*@
3806   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3807   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3808 
3809   Neighbor-wise Collective
3810 
3811   Input Parameters:
3812 + mat - the factored matrix
3813 - b   - the right-hand-side vector
3814 
3815   Output Parameter:
3816 . x - the result vector
3817 
3818   Level: developer
3819 
3820   Notes:
3821   `MatSolve()` should be used for most applications, as it performs
3822   a forward solve followed by a backward solve.
3823 
3824   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3825   call `MatForwardSolve`(A,x,x).
3826 
3827   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3828   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3829   `MatForwardSolve()` solves $U^T*D y = b$, and
3830   `MatBackwardSolve()` solves $U x = y$.
3831   Thus they do not provide a symmetric preconditioner.
3832 
3833 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3834 @*/
3835 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3836 {
3837   PetscFunctionBegin;
3838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3839   PetscValidType(mat, 1);
3840   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3841   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3842   PetscCheckSameComm(mat, 1, b, 2);
3843   PetscCheckSameComm(mat, 1, x, 3);
3844   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3845   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);
3846   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);
3847   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);
3848   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3849   MatCheckPreallocated(mat, 1);
3850 
3851   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3852   PetscUseTypeMethod(mat, forwardsolve, b, x);
3853   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3854   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3855   PetscFunctionReturn(PETSC_SUCCESS);
3856 }
3857 
3858 /*@
3859   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3860   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3861 
3862   Neighbor-wise Collective
3863 
3864   Input Parameters:
3865 + mat - the factored matrix
3866 - b   - the right-hand-side vector
3867 
3868   Output Parameter:
3869 . x - the result vector
3870 
3871   Level: developer
3872 
3873   Notes:
3874   `MatSolve()` should be used for most applications, as it performs
3875   a forward solve followed by a backward solve.
3876 
3877   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3878   call `MatBackwardSolve`(A,x,x).
3879 
3880   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3881   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3882   `MatForwardSolve()` solves $U^T*D y = b$, and
3883   `MatBackwardSolve()` solves $U x = y$.
3884   Thus they do not provide a symmetric preconditioner.
3885 
3886 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3887 @*/
3888 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3889 {
3890   PetscFunctionBegin;
3891   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3892   PetscValidType(mat, 1);
3893   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3894   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3895   PetscCheckSameComm(mat, 1, b, 2);
3896   PetscCheckSameComm(mat, 1, x, 3);
3897   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3898   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);
3899   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);
3900   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);
3901   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3902   MatCheckPreallocated(mat, 1);
3903 
3904   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3905   PetscUseTypeMethod(mat, backwardsolve, b, x);
3906   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3907   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3908   PetscFunctionReturn(PETSC_SUCCESS);
3909 }
3910 
3911 /*@
3912   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3913 
3914   Neighbor-wise Collective
3915 
3916   Input Parameters:
3917 + mat - the factored matrix
3918 . b   - the right-hand-side vector
3919 - y   - the vector to be added to
3920 
3921   Output Parameter:
3922 . x - the result vector
3923 
3924   Level: developer
3925 
3926   Note:
3927   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3928   call `MatSolveAdd`(A,x,y,x).
3929 
3930 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3931 @*/
3932 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3933 {
3934   PetscScalar one = 1.0;
3935   Vec         tmp;
3936 
3937   PetscFunctionBegin;
3938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3939   PetscValidType(mat, 1);
3940   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3941   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3942   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3943   PetscCheckSameComm(mat, 1, b, 2);
3944   PetscCheckSameComm(mat, 1, y, 3);
3945   PetscCheckSameComm(mat, 1, x, 4);
3946   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3947   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);
3948   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);
3949   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);
3950   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);
3951   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);
3952   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3953   MatCheckPreallocated(mat, 1);
3954 
3955   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3956   if (mat->factorerrortype) {
3957     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3958     PetscCall(VecSetInf(x));
3959   } else if (mat->ops->solveadd) {
3960     PetscUseTypeMethod(mat, solveadd, b, y, x);
3961   } else {
3962     /* do the solve then the add manually */
3963     if (x != y) {
3964       PetscCall(MatSolve(mat, b, x));
3965       PetscCall(VecAXPY(x, one, y));
3966     } else {
3967       PetscCall(VecDuplicate(x, &tmp));
3968       PetscCall(VecCopy(x, tmp));
3969       PetscCall(MatSolve(mat, b, x));
3970       PetscCall(VecAXPY(x, one, tmp));
3971       PetscCall(VecDestroy(&tmp));
3972     }
3973   }
3974   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3975   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3976   PetscFunctionReturn(PETSC_SUCCESS);
3977 }
3978 
3979 /*@
3980   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3981 
3982   Neighbor-wise Collective
3983 
3984   Input Parameters:
3985 + mat - the factored matrix
3986 - b   - the right-hand-side vector
3987 
3988   Output Parameter:
3989 . x - the result vector
3990 
3991   Level: developer
3992 
3993   Notes:
3994   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3995   call `MatSolveTranspose`(A,x,x).
3996 
3997   Most users should employ the `KSP` interface for linear solvers
3998   instead of working directly with matrix algebra routines such as this.
3999   See, e.g., `KSPCreate()`.
4000 
4001 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4002 @*/
4003 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4004 {
4005   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4006 
4007   PetscFunctionBegin;
4008   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4009   PetscValidType(mat, 1);
4010   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4011   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4012   PetscCheckSameComm(mat, 1, b, 2);
4013   PetscCheckSameComm(mat, 1, x, 3);
4014   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4015   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);
4016   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);
4017   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4018   MatCheckPreallocated(mat, 1);
4019   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4020   if (mat->factorerrortype) {
4021     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4022     PetscCall(VecSetInf(x));
4023   } else {
4024     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4025     PetscCall((*f)(mat, b, x));
4026   }
4027   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4028   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4029   PetscFunctionReturn(PETSC_SUCCESS);
4030 }
4031 
4032 /*@
4033   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4034   factored matrix.
4035 
4036   Neighbor-wise Collective
4037 
4038   Input Parameters:
4039 + mat - the factored matrix
4040 . b   - the right-hand-side vector
4041 - y   - the vector to be added to
4042 
4043   Output Parameter:
4044 . x - the result vector
4045 
4046   Level: developer
4047 
4048   Note:
4049   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4050   call `MatSolveTransposeAdd`(A,x,y,x).
4051 
4052 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4053 @*/
4054 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4055 {
4056   PetscScalar one = 1.0;
4057   Vec         tmp;
4058   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4059 
4060   PetscFunctionBegin;
4061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4062   PetscValidType(mat, 1);
4063   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4064   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4065   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4066   PetscCheckSameComm(mat, 1, b, 2);
4067   PetscCheckSameComm(mat, 1, y, 3);
4068   PetscCheckSameComm(mat, 1, x, 4);
4069   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4070   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);
4071   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);
4072   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);
4073   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);
4074   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4075   MatCheckPreallocated(mat, 1);
4076 
4077   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4078   if (mat->factorerrortype) {
4079     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4080     PetscCall(VecSetInf(x));
4081   } else if (f) {
4082     PetscCall((*f)(mat, b, y, x));
4083   } else {
4084     /* do the solve then the add manually */
4085     if (x != y) {
4086       PetscCall(MatSolveTranspose(mat, b, x));
4087       PetscCall(VecAXPY(x, one, y));
4088     } else {
4089       PetscCall(VecDuplicate(x, &tmp));
4090       PetscCall(VecCopy(x, tmp));
4091       PetscCall(MatSolveTranspose(mat, b, x));
4092       PetscCall(VecAXPY(x, one, tmp));
4093       PetscCall(VecDestroy(&tmp));
4094     }
4095   }
4096   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4097   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4098   PetscFunctionReturn(PETSC_SUCCESS);
4099 }
4100 
4101 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4102 /*@
4103   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4104 
4105   Neighbor-wise Collective
4106 
4107   Input Parameters:
4108 + mat   - the matrix
4109 . b     - the right hand side
4110 . omega - the relaxation factor
4111 . flag  - flag indicating the type of SOR (see below)
4112 . shift - diagonal shift
4113 . its   - the number of iterations
4114 - lits  - the number of local iterations
4115 
4116   Output Parameter:
4117 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4118 
4119   SOR Flags:
4120 +     `SOR_FORWARD_SWEEP` - forward SOR
4121 .     `SOR_BACKWARD_SWEEP` - backward SOR
4122 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4123 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4124 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4125 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4126 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4127 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4128   upper/lower triangular part of matrix to
4129   vector (with omega)
4130 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4131 
4132   Level: developer
4133 
4134   Notes:
4135   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4136   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4137   on each processor.
4138 
4139   Application programmers will not generally use `MatSOR()` directly,
4140   but instead will employ the `KSP`/`PC` interface.
4141 
4142   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4143 
4144   Most users should employ the `KSP` interface for linear solvers
4145   instead of working directly with matrix algebra routines such as this.
4146   See, e.g., `KSPCreate()`.
4147 
4148   Vectors `x` and `b` CANNOT be the same
4149 
4150   The flags are implemented as bitwise inclusive or operations.
4151   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4152   to specify a zero initial guess for SSOR.
4153 
4154   Developer Note:
4155   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4156 
4157 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4158 @*/
4159 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4160 {
4161   PetscFunctionBegin;
4162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4163   PetscValidType(mat, 1);
4164   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4165   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4166   PetscCheckSameComm(mat, 1, b, 2);
4167   PetscCheckSameComm(mat, 1, x, 8);
4168   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4169   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4170   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);
4171   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);
4172   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);
4173   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4174   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4175   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4176 
4177   MatCheckPreallocated(mat, 1);
4178   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4179   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4180   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4181   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4182   PetscFunctionReturn(PETSC_SUCCESS);
4183 }
4184 
4185 /*
4186       Default matrix copy routine.
4187 */
4188 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4189 {
4190   PetscInt           i, rstart = 0, rend = 0, nz;
4191   const PetscInt    *cwork;
4192   const PetscScalar *vwork;
4193 
4194   PetscFunctionBegin;
4195   if (B->assembled) PetscCall(MatZeroEntries(B));
4196   if (str == SAME_NONZERO_PATTERN) {
4197     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4198     for (i = rstart; i < rend; i++) {
4199       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4200       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4201       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4202     }
4203   } else {
4204     PetscCall(MatAYPX(B, 0.0, A, str));
4205   }
4206   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4207   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4208   PetscFunctionReturn(PETSC_SUCCESS);
4209 }
4210 
4211 /*@
4212   MatCopy - Copies a matrix to another matrix.
4213 
4214   Collective
4215 
4216   Input Parameters:
4217 + A   - the matrix
4218 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4219 
4220   Output Parameter:
4221 . B - where the copy is put
4222 
4223   Level: intermediate
4224 
4225   Notes:
4226   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4227 
4228   `MatCopy()` copies the matrix entries of a matrix to another existing
4229   matrix (after first zeroing the second matrix).  A related routine is
4230   `MatConvert()`, which first creates a new matrix and then copies the data.
4231 
4232 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4233 @*/
4234 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4235 {
4236   PetscInt i;
4237 
4238   PetscFunctionBegin;
4239   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4240   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4241   PetscValidType(A, 1);
4242   PetscValidType(B, 2);
4243   PetscCheckSameComm(A, 1, B, 2);
4244   MatCheckPreallocated(B, 2);
4245   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4246   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4247   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,
4248              A->cmap->N, B->cmap->N);
4249   MatCheckPreallocated(A, 1);
4250   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4251 
4252   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4253   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4254   else PetscCall(MatCopy_Basic(A, B, str));
4255 
4256   B->stencil.dim = A->stencil.dim;
4257   B->stencil.noc = A->stencil.noc;
4258   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4259     B->stencil.dims[i]   = A->stencil.dims[i];
4260     B->stencil.starts[i] = A->stencil.starts[i];
4261   }
4262 
4263   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4264   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4265   PetscFunctionReturn(PETSC_SUCCESS);
4266 }
4267 
4268 /*@C
4269   MatConvert - Converts a matrix to another matrix, either of the same
4270   or different type.
4271 
4272   Collective
4273 
4274   Input Parameters:
4275 + mat     - the matrix
4276 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4277    same type as the original matrix.
4278 - reuse   - denotes if the destination matrix is to be created or reused.
4279    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
4280    `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).
4281 
4282   Output Parameter:
4283 . M - pointer to place new matrix
4284 
4285   Level: intermediate
4286 
4287   Notes:
4288   `MatConvert()` first creates a new matrix and then copies the data from
4289   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4290   entries of one matrix to another already existing matrix context.
4291 
4292   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4293   the MPI communicator of the generated matrix is always the same as the communicator
4294   of the input matrix.
4295 
4296 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4297 @*/
4298 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4299 {
4300   PetscBool  sametype, issame, flg;
4301   PetscBool3 issymmetric, ishermitian;
4302   char       convname[256], mtype[256];
4303   Mat        B;
4304 
4305   PetscFunctionBegin;
4306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4307   PetscValidType(mat, 1);
4308   PetscAssertPointer(M, 4);
4309   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4310   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4311   MatCheckPreallocated(mat, 1);
4312 
4313   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4314   if (flg) newtype = mtype;
4315 
4316   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4317   PetscCall(PetscStrcmp(newtype, "same", &issame));
4318   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4319   if (reuse == MAT_REUSE_MATRIX) {
4320     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4321     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4322   }
4323 
4324   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4325     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4326     PetscFunctionReturn(PETSC_SUCCESS);
4327   }
4328 
4329   /* Cache Mat options because some converters use MatHeaderReplace  */
4330   issymmetric = mat->symmetric;
4331   ishermitian = mat->hermitian;
4332 
4333   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4334     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4335     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4336   } else {
4337     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4338     const char *prefix[3]                                 = {"seq", "mpi", ""};
4339     PetscInt    i;
4340     /*
4341        Order of precedence:
4342        0) See if newtype is a superclass of the current matrix.
4343        1) See if a specialized converter is known to the current matrix.
4344        2) See if a specialized converter is known to the desired matrix class.
4345        3) See if a good general converter is registered for the desired class
4346           (as of 6/27/03 only MATMPIADJ falls into this category).
4347        4) See if a good general converter is known for the current matrix.
4348        5) Use a really basic converter.
4349     */
4350 
4351     /* 0) See if newtype is a superclass of the current matrix.
4352           i.e mat is mpiaij and newtype is aij */
4353     for (i = 0; i < 2; i++) {
4354       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4355       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4356       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4357       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4358       if (flg) {
4359         if (reuse == MAT_INPLACE_MATRIX) {
4360           PetscCall(PetscInfo(mat, "Early return\n"));
4361           PetscFunctionReturn(PETSC_SUCCESS);
4362         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4363           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4364           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4365           PetscFunctionReturn(PETSC_SUCCESS);
4366         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4367           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4368           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4369           PetscFunctionReturn(PETSC_SUCCESS);
4370         }
4371       }
4372     }
4373     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4374     for (i = 0; i < 3; i++) {
4375       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4381       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4382       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4383       if (conv) goto foundconv;
4384     }
4385 
4386     /* 2)  See if a specialized converter is known to the desired matrix class. */
4387     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4388     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4389     PetscCall(MatSetType(B, newtype));
4390     for (i = 0; i < 3; i++) {
4391       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4396       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4397       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4398       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4399       if (conv) {
4400         PetscCall(MatDestroy(&B));
4401         goto foundconv;
4402       }
4403     }
4404 
4405     /* 3) See if a good general converter is registered for the desired class */
4406     conv = B->ops->convertfrom;
4407     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4408     PetscCall(MatDestroy(&B));
4409     if (conv) goto foundconv;
4410 
4411     /* 4) See if a good general converter is known for the current matrix */
4412     if (mat->ops->convert) conv = mat->ops->convert;
4413     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4414     if (conv) goto foundconv;
4415 
4416     /* 5) Use a really basic converter. */
4417     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4418     conv = MatConvert_Basic;
4419 
4420   foundconv:
4421     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4422     PetscCall((*conv)(mat, newtype, reuse, M));
4423     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4424       /* the block sizes must be same if the mappings are copied over */
4425       (*M)->rmap->bs = mat->rmap->bs;
4426       (*M)->cmap->bs = mat->cmap->bs;
4427       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4428       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4429       (*M)->rmap->mapping = mat->rmap->mapping;
4430       (*M)->cmap->mapping = mat->cmap->mapping;
4431     }
4432     (*M)->stencil.dim = mat->stencil.dim;
4433     (*M)->stencil.noc = mat->stencil.noc;
4434     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4435       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4436       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4437     }
4438     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4439   }
4440   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4441 
4442   /* Copy Mat options */
4443   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4444   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4445   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4446   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4447   PetscFunctionReturn(PETSC_SUCCESS);
4448 }
4449 
4450 /*@C
4451   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4452 
4453   Not Collective
4454 
4455   Input Parameter:
4456 . mat - the matrix, must be a factored matrix
4457 
4458   Output Parameter:
4459 . type - the string name of the package (do not free this string)
4460 
4461   Level: intermediate
4462 
4463   Fortran Note:
4464   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4465 
4466 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4467 @*/
4468 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4469 {
4470   PetscErrorCode (*conv)(Mat, MatSolverType *);
4471 
4472   PetscFunctionBegin;
4473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4474   PetscValidType(mat, 1);
4475   PetscAssertPointer(type, 2);
4476   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4477   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4478   if (conv) PetscCall((*conv)(mat, type));
4479   else *type = MATSOLVERPETSC;
4480   PetscFunctionReturn(PETSC_SUCCESS);
4481 }
4482 
4483 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4484 struct _MatSolverTypeForSpecifcType {
4485   MatType mtype;
4486   /* no entry for MAT_FACTOR_NONE */
4487   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4488   MatSolverTypeForSpecifcType next;
4489 };
4490 
4491 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4492 struct _MatSolverTypeHolder {
4493   char                       *name;
4494   MatSolverTypeForSpecifcType handlers;
4495   MatSolverTypeHolder         next;
4496 };
4497 
4498 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4499 
4500 /*@C
4501   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4502 
4503   Input Parameters:
4504 + package      - name of the package, for example petsc or superlu
4505 . mtype        - the matrix type that works with this package
4506 . ftype        - the type of factorization supported by the package
4507 - createfactor - routine that will create the factored matrix ready to be used
4508 
4509   Level: developer
4510 
4511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4512 @*/
4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4514 {
4515   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4516   PetscBool                   flg;
4517   MatSolverTypeForSpecifcType inext, iprev = NULL;
4518 
4519   PetscFunctionBegin;
4520   PetscCall(MatInitializePackage());
4521   if (!next) {
4522     PetscCall(PetscNew(&MatSolverTypeHolders));
4523     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4524     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4525     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4526     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4527     PetscFunctionReturn(PETSC_SUCCESS);
4528   }
4529   while (next) {
4530     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4531     if (flg) {
4532       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4533       inext = next->handlers;
4534       while (inext) {
4535         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4536         if (flg) {
4537           inext->createfactor[(int)ftype - 1] = createfactor;
4538           PetscFunctionReturn(PETSC_SUCCESS);
4539         }
4540         iprev = inext;
4541         inext = inext->next;
4542       }
4543       PetscCall(PetscNew(&iprev->next));
4544       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4545       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4546       PetscFunctionReturn(PETSC_SUCCESS);
4547     }
4548     prev = next;
4549     next = next->next;
4550   }
4551   PetscCall(PetscNew(&prev->next));
4552   PetscCall(PetscStrallocpy(package, &prev->next->name));
4553   PetscCall(PetscNew(&prev->next->handlers));
4554   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4555   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4556   PetscFunctionReturn(PETSC_SUCCESS);
4557 }
4558 
4559 /*@C
4560   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4561 
4562   Input Parameters:
4563 + type  - name of the package, for example petsc or superlu
4564 . ftype - the type of factorization supported by the type
4565 - mtype - the matrix type that works with this type
4566 
4567   Output Parameters:
4568 + foundtype    - `PETSC_TRUE` if the type was registered
4569 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4571 
4572   Level: developer
4573 
4574 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4575 @*/
4576 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4577 {
4578   MatSolverTypeHolder         next = MatSolverTypeHolders;
4579   PetscBool                   flg;
4580   MatSolverTypeForSpecifcType inext;
4581 
4582   PetscFunctionBegin;
4583   if (foundtype) *foundtype = PETSC_FALSE;
4584   if (foundmtype) *foundmtype = PETSC_FALSE;
4585   if (createfactor) *createfactor = NULL;
4586 
4587   if (type) {
4588     while (next) {
4589       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4590       if (flg) {
4591         if (foundtype) *foundtype = PETSC_TRUE;
4592         inext = next->handlers;
4593         while (inext) {
4594           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4595           if (flg) {
4596             if (foundmtype) *foundmtype = PETSC_TRUE;
4597             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4598             PetscFunctionReturn(PETSC_SUCCESS);
4599           }
4600           inext = inext->next;
4601         }
4602       }
4603       next = next->next;
4604     }
4605   } else {
4606     while (next) {
4607       inext = next->handlers;
4608       while (inext) {
4609         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4610         if (flg && inext->createfactor[(int)ftype - 1]) {
4611           if (foundtype) *foundtype = PETSC_TRUE;
4612           if (foundmtype) *foundmtype = PETSC_TRUE;
4613           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4614           PetscFunctionReturn(PETSC_SUCCESS);
4615         }
4616         inext = inext->next;
4617       }
4618       next = next->next;
4619     }
4620     /* try with base classes inext->mtype */
4621     next = MatSolverTypeHolders;
4622     while (next) {
4623       inext = next->handlers;
4624       while (inext) {
4625         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4626         if (flg && inext->createfactor[(int)ftype - 1]) {
4627           if (foundtype) *foundtype = PETSC_TRUE;
4628           if (foundmtype) *foundmtype = PETSC_TRUE;
4629           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4630           PetscFunctionReturn(PETSC_SUCCESS);
4631         }
4632         inext = inext->next;
4633       }
4634       next = next->next;
4635     }
4636   }
4637   PetscFunctionReturn(PETSC_SUCCESS);
4638 }
4639 
4640 PetscErrorCode MatSolverTypeDestroy(void)
4641 {
4642   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4643   MatSolverTypeForSpecifcType inext, iprev;
4644 
4645   PetscFunctionBegin;
4646   while (next) {
4647     PetscCall(PetscFree(next->name));
4648     inext = next->handlers;
4649     while (inext) {
4650       PetscCall(PetscFree(inext->mtype));
4651       iprev = inext;
4652       inext = inext->next;
4653       PetscCall(PetscFree(iprev));
4654     }
4655     prev = next;
4656     next = next->next;
4657     PetscCall(PetscFree(prev));
4658   }
4659   MatSolverTypeHolders = NULL;
4660   PetscFunctionReturn(PETSC_SUCCESS);
4661 }
4662 
4663 /*@C
4664   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4665 
4666   Logically Collective
4667 
4668   Input Parameter:
4669 . mat - the matrix
4670 
4671   Output Parameter:
4672 . flg - `PETSC_TRUE` if uses the ordering
4673 
4674   Level: developer
4675 
4676   Note:
4677   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4678   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4679 
4680 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4681 @*/
4682 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4683 {
4684   PetscFunctionBegin;
4685   *flg = mat->canuseordering;
4686   PetscFunctionReturn(PETSC_SUCCESS);
4687 }
4688 
4689 /*@C
4690   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4691 
4692   Logically Collective
4693 
4694   Input Parameters:
4695 + mat   - the matrix obtained with `MatGetFactor()`
4696 - ftype - the factorization type to be used
4697 
4698   Output Parameter:
4699 . otype - the preferred ordering type
4700 
4701   Level: developer
4702 
4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4704 @*/
4705 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4706 {
4707   PetscFunctionBegin;
4708   *otype = mat->preferredordering[ftype];
4709   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4710   PetscFunctionReturn(PETSC_SUCCESS);
4711 }
4712 
4713 /*@C
4714   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4715 
4716   Collective
4717 
4718   Input Parameters:
4719 + mat   - the matrix
4720 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4721 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4722 
4723   Output Parameter:
4724 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4725 
4726   Options Database Key:
4727 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4728                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4729 
4730   Level: intermediate
4731 
4732   Notes:
4733   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4734   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4735 
4736   Users usually access the factorization solvers via `KSP`
4737 
4738   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4739   such as pastix, superlu, mumps etc.
4740 
4741   PETSc must have been ./configure to use the external solver, using the option --download-package
4742 
4743   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4744   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4745   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4746 
4747   Developer Note:
4748   This should actually be called `MatCreateFactor()` since it creates a new factor object
4749 
4750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4751           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4752 @*/
4753 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4754 {
4755   PetscBool foundtype, foundmtype;
4756   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4757 
4758   PetscFunctionBegin;
4759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4760   PetscValidType(mat, 1);
4761 
4762   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4763   MatCheckPreallocated(mat, 1);
4764 
4765   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4766   if (!foundtype) {
4767     if (type) {
4768       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],
4769               ((PetscObject)mat)->type_name, type);
4770     } else {
4771       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);
4772     }
4773   }
4774   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4775   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);
4776 
4777   PetscCall((*conv)(mat, ftype, f));
4778   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4779   PetscFunctionReturn(PETSC_SUCCESS);
4780 }
4781 
4782 /*@C
4783   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4784 
4785   Not Collective
4786 
4787   Input Parameters:
4788 + mat   - the matrix
4789 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4790 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4791 
4792   Output Parameter:
4793 . flg - PETSC_TRUE if the factorization is available
4794 
4795   Level: intermediate
4796 
4797   Notes:
4798   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4799   such as pastix, superlu, mumps etc.
4800 
4801   PETSc must have been ./configure to use the external solver, using the option --download-package
4802 
4803   Developer Note:
4804   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4805 
4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4807           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4808 @*/
4809 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4810 {
4811   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4812 
4813   PetscFunctionBegin;
4814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4815   PetscAssertPointer(flg, 4);
4816 
4817   *flg = PETSC_FALSE;
4818   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4819 
4820   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4821   MatCheckPreallocated(mat, 1);
4822 
4823   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4824   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4825   PetscFunctionReturn(PETSC_SUCCESS);
4826 }
4827 
4828 /*@
4829   MatDuplicate - Duplicates a matrix including the non-zero structure.
4830 
4831   Collective
4832 
4833   Input Parameters:
4834 + mat - the matrix
4835 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4836         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4837 
4838   Output Parameter:
4839 . M - pointer to place new matrix
4840 
4841   Level: intermediate
4842 
4843   Notes:
4844   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4845 
4846   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4847 
4848   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.
4849 
4850   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4851   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4852   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4853 
4854 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4855 @*/
4856 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4857 {
4858   Mat         B;
4859   VecType     vtype;
4860   PetscInt    i;
4861   PetscObject dm, container_h, container_d;
4862   void (*viewf)(void);
4863 
4864   PetscFunctionBegin;
4865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4866   PetscValidType(mat, 1);
4867   PetscAssertPointer(M, 3);
4868   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4869   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4870   MatCheckPreallocated(mat, 1);
4871 
4872   *M = NULL;
4873   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4874   PetscUseTypeMethod(mat, duplicate, op, M);
4875   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4876   B = *M;
4877 
4878   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4879   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4880   PetscCall(MatGetVecType(mat, &vtype));
4881   PetscCall(MatSetVecType(B, vtype));
4882 
4883   B->stencil.dim = mat->stencil.dim;
4884   B->stencil.noc = mat->stencil.noc;
4885   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4886     B->stencil.dims[i]   = mat->stencil.dims[i];
4887     B->stencil.starts[i] = mat->stencil.starts[i];
4888   }
4889 
4890   B->nooffproczerorows = mat->nooffproczerorows;
4891   B->nooffprocentries  = mat->nooffprocentries;
4892 
4893   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4894   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4895   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4896   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4897   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4898   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4899   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4900   PetscFunctionReturn(PETSC_SUCCESS);
4901 }
4902 
4903 /*@
4904   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4905 
4906   Logically Collective
4907 
4908   Input Parameter:
4909 . mat - the matrix
4910 
4911   Output Parameter:
4912 . v - the diagonal of the matrix
4913 
4914   Level: intermediate
4915 
4916   Note:
4917   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4918   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4919   is larger than `ndiag`, the values of the remaining entries are unspecified.
4920 
4921   Currently only correct in parallel for square matrices.
4922 
4923 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4924 @*/
4925 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4926 {
4927   PetscFunctionBegin;
4928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4929   PetscValidType(mat, 1);
4930   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4931   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4932   MatCheckPreallocated(mat, 1);
4933   if (PetscDefined(USE_DEBUG)) {
4934     PetscInt nv, row, col, ndiag;
4935 
4936     PetscCall(VecGetLocalSize(v, &nv));
4937     PetscCall(MatGetLocalSize(mat, &row, &col));
4938     ndiag = PetscMin(row, col);
4939     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);
4940   }
4941 
4942   PetscUseTypeMethod(mat, getdiagonal, v);
4943   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4944   PetscFunctionReturn(PETSC_SUCCESS);
4945 }
4946 
4947 /*@C
4948   MatGetRowMin - Gets the minimum value (of the real part) of each
4949   row of the matrix
4950 
4951   Logically Collective
4952 
4953   Input Parameter:
4954 . mat - the matrix
4955 
4956   Output Parameters:
4957 + v   - the vector for storing the maximums
4958 - idx - the indices of the column found for each row (optional)
4959 
4960   Level: intermediate
4961 
4962   Note:
4963   The result of this call are the same as if one converted the matrix to dense format
4964   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4965 
4966   This code is only implemented for a couple of matrix formats.
4967 
4968 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4969           `MatGetRowMax()`
4970 @*/
4971 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4972 {
4973   PetscFunctionBegin;
4974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4975   PetscValidType(mat, 1);
4976   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4977   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4978 
4979   if (!mat->cmap->N) {
4980     PetscCall(VecSet(v, PETSC_MAX_REAL));
4981     if (idx) {
4982       PetscInt i, m = mat->rmap->n;
4983       for (i = 0; i < m; i++) idx[i] = -1;
4984     }
4985   } else {
4986     MatCheckPreallocated(mat, 1);
4987   }
4988   PetscUseTypeMethod(mat, getrowmin, v, idx);
4989   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4990   PetscFunctionReturn(PETSC_SUCCESS);
4991 }
4992 
4993 /*@C
4994   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4995   row of the matrix
4996 
4997   Logically Collective
4998 
4999   Input Parameter:
5000 . mat - the matrix
5001 
5002   Output Parameters:
5003 + v   - the vector for storing the minimums
5004 - idx - the indices of the column found for each row (or `NULL` if not needed)
5005 
5006   Level: intermediate
5007 
5008   Notes:
5009   if a row is completely empty or has only 0.0 values then the `idx` value for that
5010   row is 0 (the first column).
5011 
5012   This code is only implemented for a couple of matrix formats.
5013 
5014 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5015 @*/
5016 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5017 {
5018   PetscFunctionBegin;
5019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5020   PetscValidType(mat, 1);
5021   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5022   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5023   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5024 
5025   if (!mat->cmap->N) {
5026     PetscCall(VecSet(v, 0.0));
5027     if (idx) {
5028       PetscInt i, m = mat->rmap->n;
5029       for (i = 0; i < m; i++) idx[i] = -1;
5030     }
5031   } else {
5032     MatCheckPreallocated(mat, 1);
5033     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5034     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5035   }
5036   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5037   PetscFunctionReturn(PETSC_SUCCESS);
5038 }
5039 
5040 /*@C
5041   MatGetRowMax - Gets the maximum value (of the real part) of each
5042   row of the matrix
5043 
5044   Logically Collective
5045 
5046   Input Parameter:
5047 . mat - the matrix
5048 
5049   Output Parameters:
5050 + v   - the vector for storing the maximums
5051 - idx - the indices of the column found for each row (optional)
5052 
5053   Level: intermediate
5054 
5055   Notes:
5056   The result of this call are the same as if one converted the matrix to dense format
5057   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5058 
5059   This code is only implemented for a couple of matrix formats.
5060 
5061 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5062 @*/
5063 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5064 {
5065   PetscFunctionBegin;
5066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5067   PetscValidType(mat, 1);
5068   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5069   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5070 
5071   if (!mat->cmap->N) {
5072     PetscCall(VecSet(v, PETSC_MIN_REAL));
5073     if (idx) {
5074       PetscInt i, m = mat->rmap->n;
5075       for (i = 0; i < m; i++) idx[i] = -1;
5076     }
5077   } else {
5078     MatCheckPreallocated(mat, 1);
5079     PetscUseTypeMethod(mat, getrowmax, v, idx);
5080   }
5081   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5082   PetscFunctionReturn(PETSC_SUCCESS);
5083 }
5084 
5085 /*@C
5086   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5087   row of the matrix
5088 
5089   Logically Collective
5090 
5091   Input Parameter:
5092 . mat - the matrix
5093 
5094   Output Parameters:
5095 + v   - the vector for storing the maximums
5096 - idx - the indices of the column found for each row (or `NULL` if not needed)
5097 
5098   Level: intermediate
5099 
5100   Notes:
5101   if a row is completely empty or has only 0.0 values then the `idx` value for that
5102   row is 0 (the first column).
5103 
5104   This code is only implemented for a couple of matrix formats.
5105 
5106 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5107 @*/
5108 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5109 {
5110   PetscFunctionBegin;
5111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5112   PetscValidType(mat, 1);
5113   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5114   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5115 
5116   if (!mat->cmap->N) {
5117     PetscCall(VecSet(v, 0.0));
5118     if (idx) {
5119       PetscInt i, m = mat->rmap->n;
5120       for (i = 0; i < m; i++) idx[i] = -1;
5121     }
5122   } else {
5123     MatCheckPreallocated(mat, 1);
5124     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5125     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5126   }
5127   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5128   PetscFunctionReturn(PETSC_SUCCESS);
5129 }
5130 
5131 /*@
5132   MatGetRowSum - Gets the sum of each row of the matrix
5133 
5134   Logically or Neighborhood Collective
5135 
5136   Input Parameter:
5137 . mat - the matrix
5138 
5139   Output Parameter:
5140 . v - the vector for storing the sum of rows
5141 
5142   Level: intermediate
5143 
5144   Note:
5145   This code is slow since it is not currently specialized for different formats
5146 
5147 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5148 @*/
5149 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5150 {
5151   Vec ones;
5152 
5153   PetscFunctionBegin;
5154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5155   PetscValidType(mat, 1);
5156   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5157   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5158   MatCheckPreallocated(mat, 1);
5159   PetscCall(MatCreateVecs(mat, &ones, NULL));
5160   PetscCall(VecSet(ones, 1.));
5161   PetscCall(MatMult(mat, ones, v));
5162   PetscCall(VecDestroy(&ones));
5163   PetscFunctionReturn(PETSC_SUCCESS);
5164 }
5165 
5166 /*@
5167   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5168   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5169 
5170   Collective
5171 
5172   Input Parameter:
5173 . mat - the matrix to provide the transpose
5174 
5175   Output Parameter:
5176 . 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
5177 
5178   Level: advanced
5179 
5180   Note:
5181   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
5182   routine allows bypassing that call.
5183 
5184 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5185 @*/
5186 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5187 {
5188   PetscContainer  rB = NULL;
5189   MatParentState *rb = NULL;
5190 
5191   PetscFunctionBegin;
5192   PetscCall(PetscNew(&rb));
5193   rb->id    = ((PetscObject)mat)->id;
5194   rb->state = 0;
5195   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5196   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5197   PetscCall(PetscContainerSetPointer(rB, rb));
5198   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5199   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5200   PetscCall(PetscObjectDereference((PetscObject)rB));
5201   PetscFunctionReturn(PETSC_SUCCESS);
5202 }
5203 
5204 /*@
5205   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5206 
5207   Collective
5208 
5209   Input Parameters:
5210 + mat   - the matrix to transpose
5211 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5212 
5213   Output Parameter:
5214 . B - the transpose
5215 
5216   Level: intermediate
5217 
5218   Notes:
5219   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5220 
5221   `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
5222   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5223 
5224   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.
5225 
5226   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5227 
5228   If mat is unchanged from the last call this function returns immediately without recomputing the result
5229 
5230   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5231 
5232 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5233           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5234 @*/
5235 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5236 {
5237   PetscContainer  rB = NULL;
5238   MatParentState *rb = NULL;
5239 
5240   PetscFunctionBegin;
5241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5242   PetscValidType(mat, 1);
5243   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5244   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5245   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5246   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5247   MatCheckPreallocated(mat, 1);
5248   if (reuse == MAT_REUSE_MATRIX) {
5249     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5250     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5251     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5252     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5253     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5254   }
5255 
5256   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5257   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5258     PetscUseTypeMethod(mat, transpose, reuse, B);
5259     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5260   }
5261   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5262 
5263   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5264   if (reuse != MAT_INPLACE_MATRIX) {
5265     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5266     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5267     rb->state        = ((PetscObject)mat)->state;
5268     rb->nonzerostate = mat->nonzerostate;
5269   }
5270   PetscFunctionReturn(PETSC_SUCCESS);
5271 }
5272 
5273 /*@
5274   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5275 
5276   Collective
5277 
5278   Input Parameter:
5279 . A - the matrix to transpose
5280 
5281   Output Parameter:
5282 . 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
5283       numerical portion.
5284 
5285   Level: intermediate
5286 
5287   Note:
5288   This is not supported for many matrix types, use `MatTranspose()` in those cases
5289 
5290 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5291 @*/
5292 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5293 {
5294   PetscFunctionBegin;
5295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5296   PetscValidType(A, 1);
5297   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5298   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5299   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5300   PetscUseTypeMethod(A, transposesymbolic, B);
5301   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5302 
5303   PetscCall(MatTransposeSetPrecursor(A, *B));
5304   PetscFunctionReturn(PETSC_SUCCESS);
5305 }
5306 
5307 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5308 {
5309   PetscContainer  rB;
5310   MatParentState *rb;
5311 
5312   PetscFunctionBegin;
5313   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5314   PetscValidType(A, 1);
5315   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5316   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5317   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5318   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5319   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5320   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5321   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5322   PetscFunctionReturn(PETSC_SUCCESS);
5323 }
5324 
5325 /*@
5326   MatIsTranspose - Test whether a matrix is another one's transpose,
5327   or its own, in which case it tests symmetry.
5328 
5329   Collective
5330 
5331   Input Parameters:
5332 + A   - the matrix to test
5333 . B   - the matrix to test against, this can equal the first parameter
5334 - tol - tolerance, differences between entries smaller than this are counted as zero
5335 
5336   Output Parameter:
5337 . flg - the result
5338 
5339   Level: intermediate
5340 
5341   Notes:
5342   Only available for `MATAIJ` matrices.
5343 
5344   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5345   test involves parallel copies of the block off-diagonal parts of the matrix.
5346 
5347 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5348 @*/
5349 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5350 {
5351   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5352 
5353   PetscFunctionBegin;
5354   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5355   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5356   PetscAssertPointer(flg, 4);
5357   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5358   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5359   *flg = PETSC_FALSE;
5360   if (f && g) {
5361     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5362     PetscCall((*f)(A, B, tol, flg));
5363   } else {
5364     MatType mattype;
5365 
5366     PetscCall(MatGetType(f ? B : A, &mattype));
5367     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5368   }
5369   PetscFunctionReturn(PETSC_SUCCESS);
5370 }
5371 
5372 /*@
5373   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5374 
5375   Collective
5376 
5377   Input Parameters:
5378 + mat   - the matrix to transpose and complex conjugate
5379 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5380 
5381   Output Parameter:
5382 . B - the Hermitian transpose
5383 
5384   Level: intermediate
5385 
5386 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5387 @*/
5388 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5389 {
5390   PetscFunctionBegin;
5391   PetscCall(MatTranspose(mat, reuse, B));
5392 #if defined(PETSC_USE_COMPLEX)
5393   PetscCall(MatConjugate(*B));
5394 #endif
5395   PetscFunctionReturn(PETSC_SUCCESS);
5396 }
5397 
5398 /*@
5399   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5400 
5401   Collective
5402 
5403   Input Parameters:
5404 + A   - the matrix to test
5405 . B   - the matrix to test against, this can equal the first parameter
5406 - tol - tolerance, differences between entries smaller than this are counted as zero
5407 
5408   Output Parameter:
5409 . flg - the result
5410 
5411   Level: intermediate
5412 
5413   Notes:
5414   Only available for `MATAIJ` matrices.
5415 
5416   The sequential algorithm
5417   has a running time of the order of the number of nonzeros; the parallel
5418   test involves parallel copies of the block off-diagonal parts of the matrix.
5419 
5420 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5421 @*/
5422 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5423 {
5424   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5425 
5426   PetscFunctionBegin;
5427   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5428   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5429   PetscAssertPointer(flg, 4);
5430   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5431   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5432   if (f && g) {
5433     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5434     PetscCall((*f)(A, B, tol, flg));
5435   }
5436   PetscFunctionReturn(PETSC_SUCCESS);
5437 }
5438 
5439 /*@
5440   MatPermute - Creates a new matrix with rows and columns permuted from the
5441   original.
5442 
5443   Collective
5444 
5445   Input Parameters:
5446 + mat - the matrix to permute
5447 . row - row permutation, each processor supplies only the permutation for its rows
5448 - col - column permutation, each processor supplies only the permutation for its columns
5449 
5450   Output Parameter:
5451 . B - the permuted matrix
5452 
5453   Level: advanced
5454 
5455   Note:
5456   The index sets map from row/col of permuted matrix to row/col of original matrix.
5457   The index sets should be on the same communicator as mat and have the same local sizes.
5458 
5459   Developer Note:
5460   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5461   exploit the fact that row and col are permutations, consider implementing the
5462   more general `MatCreateSubMatrix()` instead.
5463 
5464 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5465 @*/
5466 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5467 {
5468   PetscFunctionBegin;
5469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5470   PetscValidType(mat, 1);
5471   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5472   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5473   PetscAssertPointer(B, 4);
5474   PetscCheckSameComm(mat, 1, row, 2);
5475   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5476   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5477   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5478   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5479   MatCheckPreallocated(mat, 1);
5480 
5481   if (mat->ops->permute) {
5482     PetscUseTypeMethod(mat, permute, row, col, B);
5483     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5484   } else {
5485     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5486   }
5487   PetscFunctionReturn(PETSC_SUCCESS);
5488 }
5489 
5490 /*@
5491   MatEqual - Compares two matrices.
5492 
5493   Collective
5494 
5495   Input Parameters:
5496 + A - the first matrix
5497 - B - the second matrix
5498 
5499   Output Parameter:
5500 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5501 
5502   Level: intermediate
5503 
5504 .seealso: [](ch_matrices), `Mat`
5505 @*/
5506 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5507 {
5508   PetscFunctionBegin;
5509   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5510   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5511   PetscValidType(A, 1);
5512   PetscValidType(B, 2);
5513   PetscAssertPointer(flg, 3);
5514   PetscCheckSameComm(A, 1, B, 2);
5515   MatCheckPreallocated(A, 1);
5516   MatCheckPreallocated(B, 2);
5517   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5518   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5519   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,
5520              B->cmap->N);
5521   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5522     PetscUseTypeMethod(A, equal, B, flg);
5523   } else {
5524     PetscCall(MatMultEqual(A, B, 10, flg));
5525   }
5526   PetscFunctionReturn(PETSC_SUCCESS);
5527 }
5528 
5529 /*@
5530   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5531   matrices that are stored as vectors.  Either of the two scaling
5532   matrices can be `NULL`.
5533 
5534   Collective
5535 
5536   Input Parameters:
5537 + mat - the matrix to be scaled
5538 . l   - the left scaling vector (or `NULL`)
5539 - r   - the right scaling vector (or `NULL`)
5540 
5541   Level: intermediate
5542 
5543   Note:
5544   `MatDiagonalScale()` computes $A = LAR$, where
5545   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5546   The L scales the rows of the matrix, the R scales the columns of the matrix.
5547 
5548 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5549 @*/
5550 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5551 {
5552   PetscFunctionBegin;
5553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5554   PetscValidType(mat, 1);
5555   if (l) {
5556     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5557     PetscCheckSameComm(mat, 1, l, 2);
5558   }
5559   if (r) {
5560     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5561     PetscCheckSameComm(mat, 1, r, 3);
5562   }
5563   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5564   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5565   MatCheckPreallocated(mat, 1);
5566   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5567 
5568   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5569   PetscUseTypeMethod(mat, diagonalscale, l, r);
5570   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5571   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5572   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5573   PetscFunctionReturn(PETSC_SUCCESS);
5574 }
5575 
5576 /*@
5577   MatScale - Scales all elements of a matrix by a given number.
5578 
5579   Logically Collective
5580 
5581   Input Parameters:
5582 + mat - the matrix to be scaled
5583 - a   - the scaling value
5584 
5585   Level: intermediate
5586 
5587 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5588 @*/
5589 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5590 {
5591   PetscFunctionBegin;
5592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5593   PetscValidType(mat, 1);
5594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5595   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5596   PetscValidLogicalCollectiveScalar(mat, a, 2);
5597   MatCheckPreallocated(mat, 1);
5598 
5599   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5600   if (a != (PetscScalar)1.0) {
5601     PetscUseTypeMethod(mat, scale, a);
5602     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5603   }
5604   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5605   PetscFunctionReturn(PETSC_SUCCESS);
5606 }
5607 
5608 /*@
5609   MatNorm - Calculates various norms of a matrix.
5610 
5611   Collective
5612 
5613   Input Parameters:
5614 + mat  - the matrix
5615 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5616 
5617   Output Parameter:
5618 . nrm - the resulting norm
5619 
5620   Level: intermediate
5621 
5622 .seealso: [](ch_matrices), `Mat`
5623 @*/
5624 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5625 {
5626   PetscFunctionBegin;
5627   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5628   PetscValidType(mat, 1);
5629   PetscAssertPointer(nrm, 3);
5630 
5631   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5632   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5633   MatCheckPreallocated(mat, 1);
5634 
5635   PetscUseTypeMethod(mat, norm, type, nrm);
5636   PetscFunctionReturn(PETSC_SUCCESS);
5637 }
5638 
5639 /*
5640      This variable is used to prevent counting of MatAssemblyBegin() that
5641    are called from within a MatAssemblyEnd().
5642 */
5643 static PetscInt MatAssemblyEnd_InUse = 0;
5644 /*@
5645   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5646   be called after completing all calls to `MatSetValues()`.
5647 
5648   Collective
5649 
5650   Input Parameters:
5651 + mat  - the matrix
5652 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5653 
5654   Level: beginner
5655 
5656   Notes:
5657   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5658   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5659 
5660   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5661   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5662   using the matrix.
5663 
5664   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5665   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
5666   a global collective operation requiring all processes that share the matrix.
5667 
5668   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5669   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5670   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5671 
5672 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5673 @*/
5674 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5675 {
5676   PetscFunctionBegin;
5677   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5678   PetscValidType(mat, 1);
5679   MatCheckPreallocated(mat, 1);
5680   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5681   if (mat->assembled) {
5682     mat->was_assembled = PETSC_TRUE;
5683     mat->assembled     = PETSC_FALSE;
5684   }
5685 
5686   if (!MatAssemblyEnd_InUse) {
5687     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5688     PetscTryTypeMethod(mat, assemblybegin, type);
5689     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5690   } else PetscTryTypeMethod(mat, assemblybegin, type);
5691   PetscFunctionReturn(PETSC_SUCCESS);
5692 }
5693 
5694 /*@
5695   MatAssembled - Indicates if a matrix has been assembled and is ready for
5696   use; for example, in matrix-vector product.
5697 
5698   Not Collective
5699 
5700   Input Parameter:
5701 . mat - the matrix
5702 
5703   Output Parameter:
5704 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5705 
5706   Level: advanced
5707 
5708 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5709 @*/
5710 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5711 {
5712   PetscFunctionBegin;
5713   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5714   PetscAssertPointer(assembled, 2);
5715   *assembled = mat->assembled;
5716   PetscFunctionReturn(PETSC_SUCCESS);
5717 }
5718 
5719 /*@
5720   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5721   be called after `MatAssemblyBegin()`.
5722 
5723   Collective
5724 
5725   Input Parameters:
5726 + mat  - the matrix
5727 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5728 
5729   Options Database Keys:
5730 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5731 . -mat_view ::ascii_info_detail      - Prints more detailed info
5732 . -mat_view                          - Prints matrix in ASCII format
5733 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5734 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5735 . -display <name>                    - Sets display name (default is host)
5736 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5737 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5738 . -viewer_socket_machine <machine>   - Machine to use for socket
5739 . -viewer_socket_port <port>         - Port number to use for socket
5740 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5741 
5742   Level: beginner
5743 
5744 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5745 @*/
5746 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5747 {
5748   static PetscInt inassm = 0;
5749   PetscBool       flg    = PETSC_FALSE;
5750 
5751   PetscFunctionBegin;
5752   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5753   PetscValidType(mat, 1);
5754 
5755   inassm++;
5756   MatAssemblyEnd_InUse++;
5757   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5758     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5759     PetscTryTypeMethod(mat, assemblyend, type);
5760     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5761   } else PetscTryTypeMethod(mat, assemblyend, type);
5762 
5763   /* Flush assembly is not a true assembly */
5764   if (type != MAT_FLUSH_ASSEMBLY) {
5765     if (mat->num_ass) {
5766       if (!mat->symmetry_eternal) {
5767         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5768         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5769       }
5770       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5771       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5772     }
5773     mat->num_ass++;
5774     mat->assembled        = PETSC_TRUE;
5775     mat->ass_nonzerostate = mat->nonzerostate;
5776   }
5777 
5778   mat->insertmode = NOT_SET_VALUES;
5779   MatAssemblyEnd_InUse--;
5780   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5781   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5782     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5783 
5784     if (mat->checksymmetryonassembly) {
5785       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5786       if (flg) {
5787         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5788       } else {
5789         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5790       }
5791     }
5792     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5793   }
5794   inassm--;
5795   PetscFunctionReturn(PETSC_SUCCESS);
5796 }
5797 
5798 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5799 /*@
5800   MatSetOption - Sets a parameter option for a matrix. Some options
5801   may be specific to certain storage formats.  Some options
5802   determine how values will be inserted (or added). Sorted,
5803   row-oriented input will generally assemble the fastest. The default
5804   is row-oriented.
5805 
5806   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5807 
5808   Input Parameters:
5809 + mat - the matrix
5810 . op  - the option, one of those listed below (and possibly others),
5811 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5812 
5813   Options Describing Matrix Structure:
5814 + `MAT_SPD`                         - symmetric positive definite
5815 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5816 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5817 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5818 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5819 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5820 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5821 
5822    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5823    do not need to be computed (usually at a high cost)
5824 
5825    Options For Use with `MatSetValues()`:
5826    Insert a logically dense subblock, which can be
5827 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5828 
5829    These options reflect the data you pass in with `MatSetValues()`; it has
5830    nothing to do with how the data is stored internally in the matrix
5831    data structure.
5832 
5833    When (re)assembling a matrix, we can restrict the input for
5834    efficiency/debugging purposes.  These options include
5835 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5836 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5837 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5838 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5839 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5840 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5841         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5842         performance for very large process counts.
5843 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5844         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5845         functions, instead sending only neighbor messages.
5846 
5847   Level: intermediate
5848 
5849   Notes:
5850   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5851 
5852   Some options are relevant only for particular matrix types and
5853   are thus ignored by others.  Other options are not supported by
5854   certain matrix types and will generate an error message if set.
5855 
5856   If using Fortran to compute a matrix, one may need to
5857   use the column-oriented option (or convert to the row-oriented
5858   format).
5859 
5860   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5861   that would generate a new entry in the nonzero structure is instead
5862   ignored.  Thus, if memory has not already been allocated for this particular
5863   data, then the insertion is ignored. For dense matrices, in which
5864   the entire array is allocated, no entries are ever ignored.
5865   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5866 
5867   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5868   that would generate a new entry in the nonzero structure instead produces
5869   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
5870 
5871   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5872   that would generate a new entry that has not been preallocated will
5873   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5874   only.) This is a useful flag when debugging matrix memory preallocation.
5875   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5876 
5877   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5878   other processors should be dropped, rather than stashed.
5879   This is useful if you know that the "owning" processor is also
5880   always generating the correct matrix entries, so that PETSc need
5881   not transfer duplicate entries generated on another processor.
5882 
5883   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5884   searches during matrix assembly. When this flag is set, the hash table
5885   is created during the first matrix assembly. This hash table is
5886   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5887   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5888   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5889   supported by `MATMPIBAIJ` format only.
5890 
5891   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5892   are kept in the nonzero structure
5893 
5894   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5895   a zero location in the matrix
5896 
5897   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5898 
5899   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5900   zero row routines and thus improves performance for very large process counts.
5901 
5902   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5903   part of the matrix (since they should match the upper triangular part).
5904 
5905   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5906   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5907   with finite difference schemes with non-periodic boundary conditions.
5908 
5909   Developer Note:
5910   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5911   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5912   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5913   not changed.
5914 
5915 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5916 @*/
5917 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5918 {
5919   PetscFunctionBegin;
5920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5921   if (op > 0) {
5922     PetscValidLogicalCollectiveEnum(mat, op, 2);
5923     PetscValidLogicalCollectiveBool(mat, flg, 3);
5924   }
5925 
5926   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);
5927 
5928   switch (op) {
5929   case MAT_FORCE_DIAGONAL_ENTRIES:
5930     mat->force_diagonals = flg;
5931     PetscFunctionReturn(PETSC_SUCCESS);
5932   case MAT_NO_OFF_PROC_ENTRIES:
5933     mat->nooffprocentries = flg;
5934     PetscFunctionReturn(PETSC_SUCCESS);
5935   case MAT_SUBSET_OFF_PROC_ENTRIES:
5936     mat->assembly_subset = flg;
5937     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5938 #if !defined(PETSC_HAVE_MPIUNI)
5939       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5940 #endif
5941       mat->stash.first_assembly_done = PETSC_FALSE;
5942     }
5943     PetscFunctionReturn(PETSC_SUCCESS);
5944   case MAT_NO_OFF_PROC_ZERO_ROWS:
5945     mat->nooffproczerorows = flg;
5946     PetscFunctionReturn(PETSC_SUCCESS);
5947   case MAT_SPD:
5948     if (flg) {
5949       mat->spd                    = PETSC_BOOL3_TRUE;
5950       mat->symmetric              = PETSC_BOOL3_TRUE;
5951       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5952     } else {
5953       mat->spd = PETSC_BOOL3_FALSE;
5954     }
5955     break;
5956   case MAT_SYMMETRIC:
5957     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5958     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5959 #if !defined(PETSC_USE_COMPLEX)
5960     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5961 #endif
5962     break;
5963   case MAT_HERMITIAN:
5964     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5965     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5966 #if !defined(PETSC_USE_COMPLEX)
5967     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5968 #endif
5969     break;
5970   case MAT_STRUCTURALLY_SYMMETRIC:
5971     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5972     break;
5973   case MAT_SYMMETRY_ETERNAL:
5974     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");
5975     mat->symmetry_eternal = flg;
5976     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5977     break;
5978   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5979     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");
5980     mat->structural_symmetry_eternal = flg;
5981     break;
5982   case MAT_SPD_ETERNAL:
5983     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");
5984     mat->spd_eternal = flg;
5985     if (flg) {
5986       mat->structural_symmetry_eternal = PETSC_TRUE;
5987       mat->symmetry_eternal            = PETSC_TRUE;
5988     }
5989     break;
5990   case MAT_STRUCTURE_ONLY:
5991     mat->structure_only = flg;
5992     break;
5993   case MAT_SORTED_FULL:
5994     mat->sortedfull = flg;
5995     break;
5996   default:
5997     break;
5998   }
5999   PetscTryTypeMethod(mat, setoption, op, flg);
6000   PetscFunctionReturn(PETSC_SUCCESS);
6001 }
6002 
6003 /*@
6004   MatGetOption - Gets a parameter option that has been set for a matrix.
6005 
6006   Logically Collective
6007 
6008   Input Parameters:
6009 + mat - the matrix
6010 - op  - the option, this only responds to certain options, check the code for which ones
6011 
6012   Output Parameter:
6013 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6014 
6015   Level: intermediate
6016 
6017   Notes:
6018   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6019 
6020   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6021   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6022 
6023 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6024     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6025 @*/
6026 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6027 {
6028   PetscFunctionBegin;
6029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6030   PetscValidType(mat, 1);
6031 
6032   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);
6033   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()");
6034 
6035   switch (op) {
6036   case MAT_NO_OFF_PROC_ENTRIES:
6037     *flg = mat->nooffprocentries;
6038     break;
6039   case MAT_NO_OFF_PROC_ZERO_ROWS:
6040     *flg = mat->nooffproczerorows;
6041     break;
6042   case MAT_SYMMETRIC:
6043     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6044     break;
6045   case MAT_HERMITIAN:
6046     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6047     break;
6048   case MAT_STRUCTURALLY_SYMMETRIC:
6049     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6050     break;
6051   case MAT_SPD:
6052     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6053     break;
6054   case MAT_SYMMETRY_ETERNAL:
6055     *flg = mat->symmetry_eternal;
6056     break;
6057   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6058     *flg = mat->symmetry_eternal;
6059     break;
6060   default:
6061     break;
6062   }
6063   PetscFunctionReturn(PETSC_SUCCESS);
6064 }
6065 
6066 /*@
6067   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6068   this routine retains the old nonzero structure.
6069 
6070   Logically Collective
6071 
6072   Input Parameter:
6073 . mat - the matrix
6074 
6075   Level: intermediate
6076 
6077   Note:
6078   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.
6079   See the Performance chapter of the users manual for information on preallocating matrices.
6080 
6081 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6082 @*/
6083 PetscErrorCode MatZeroEntries(Mat mat)
6084 {
6085   PetscFunctionBegin;
6086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6087   PetscValidType(mat, 1);
6088   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6089   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");
6090   MatCheckPreallocated(mat, 1);
6091 
6092   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6093   PetscUseTypeMethod(mat, zeroentries);
6094   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6095   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6096   PetscFunctionReturn(PETSC_SUCCESS);
6097 }
6098 
6099 /*@
6100   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6101   of a set of rows and columns of a matrix.
6102 
6103   Collective
6104 
6105   Input Parameters:
6106 + mat     - the matrix
6107 . numRows - the number of rows/columns to zero
6108 . rows    - the global row indices
6109 . diag    - value put in the diagonal of the eliminated rows
6110 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6111 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6112 
6113   Level: intermediate
6114 
6115   Notes:
6116   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6117 
6118   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6119   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
6120 
6121   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6122   Krylov method to take advantage of the known solution on the zeroed rows.
6123 
6124   For the parallel case, all processes that share the matrix (i.e.,
6125   those in the communicator used for matrix creation) MUST call this
6126   routine, regardless of whether any rows being zeroed are owned by
6127   them.
6128 
6129   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6130 
6131   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6132   list only rows local to itself).
6133 
6134   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6135 
6136 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6137           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6138 @*/
6139 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6140 {
6141   PetscFunctionBegin;
6142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6143   PetscValidType(mat, 1);
6144   if (numRows) PetscAssertPointer(rows, 3);
6145   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6146   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6147   MatCheckPreallocated(mat, 1);
6148 
6149   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6150   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6151   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6152   PetscFunctionReturn(PETSC_SUCCESS);
6153 }
6154 
6155 /*@
6156   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6157   of a set of rows and columns of a matrix.
6158 
6159   Collective
6160 
6161   Input Parameters:
6162 + mat  - the matrix
6163 . is   - the rows to zero
6164 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6165 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6166 - b    - optional vector of right hand side, that will be adjusted by provided solution
6167 
6168   Level: intermediate
6169 
6170   Note:
6171   See `MatZeroRowsColumns()` for details on how this routine operates.
6172 
6173 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6174           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6175 @*/
6176 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6177 {
6178   PetscInt        numRows;
6179   const PetscInt *rows;
6180 
6181   PetscFunctionBegin;
6182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6183   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6184   PetscValidType(mat, 1);
6185   PetscValidType(is, 2);
6186   PetscCall(ISGetLocalSize(is, &numRows));
6187   PetscCall(ISGetIndices(is, &rows));
6188   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6189   PetscCall(ISRestoreIndices(is, &rows));
6190   PetscFunctionReturn(PETSC_SUCCESS);
6191 }
6192 
6193 /*@
6194   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6195   of a set of rows of a matrix.
6196 
6197   Collective
6198 
6199   Input Parameters:
6200 + mat     - the matrix
6201 . numRows - the number of rows to zero
6202 . rows    - the global row indices
6203 . diag    - value put in the diagonal of the zeroed rows
6204 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6205 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6206 
6207   Level: intermediate
6208 
6209   Notes:
6210   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6211 
6212   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6213 
6214   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6215   Krylov method to take advantage of the known solution on the zeroed rows.
6216 
6217   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)
6218   from the matrix.
6219 
6220   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6221   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
6222   formats this does not alter the nonzero structure.
6223 
6224   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6225   of the matrix is not changed the values are
6226   merely zeroed.
6227 
6228   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6229   formats can optionally remove the main diagonal entry from the
6230   nonzero structure as well, by passing 0.0 as the final argument).
6231 
6232   For the parallel case, all processes that share the matrix (i.e.,
6233   those in the communicator used for matrix creation) MUST call this
6234   routine, regardless of whether any rows being zeroed are owned by
6235   them.
6236 
6237   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6238   list only rows local to itself).
6239 
6240   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6241   owns that are to be zeroed. This saves a global synchronization in the implementation.
6242 
6243 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6244           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6245 @*/
6246 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6247 {
6248   PetscFunctionBegin;
6249   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6250   PetscValidType(mat, 1);
6251   if (numRows) PetscAssertPointer(rows, 3);
6252   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6253   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6254   MatCheckPreallocated(mat, 1);
6255 
6256   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6257   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6258   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6259   PetscFunctionReturn(PETSC_SUCCESS);
6260 }
6261 
6262 /*@
6263   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6264   of a set of rows of a matrix.
6265 
6266   Collective
6267 
6268   Input Parameters:
6269 + mat  - the matrix
6270 . is   - index set of rows to remove (if `NULL` then no row is removed)
6271 . diag - value put in all diagonals of eliminated rows
6272 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6273 - b    - optional vector of right hand side, that will be adjusted by provided solution
6274 
6275   Level: intermediate
6276 
6277   Note:
6278   See `MatZeroRows()` for details on how this routine operates.
6279 
6280 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6281           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6282 @*/
6283 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6284 {
6285   PetscInt        numRows = 0;
6286   const PetscInt *rows    = NULL;
6287 
6288   PetscFunctionBegin;
6289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6290   PetscValidType(mat, 1);
6291   if (is) {
6292     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6293     PetscCall(ISGetLocalSize(is, &numRows));
6294     PetscCall(ISGetIndices(is, &rows));
6295   }
6296   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6297   if (is) PetscCall(ISRestoreIndices(is, &rows));
6298   PetscFunctionReturn(PETSC_SUCCESS);
6299 }
6300 
6301 /*@
6302   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6303   of a set of rows of a matrix. These rows must be local to the process.
6304 
6305   Collective
6306 
6307   Input Parameters:
6308 + mat     - the matrix
6309 . numRows - the number of rows to remove
6310 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6311 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6312 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6313 - b       - optional vector of right hand side, that will be adjusted by provided solution
6314 
6315   Level: intermediate
6316 
6317   Notes:
6318   See `MatZeroRows()` for details on how this routine operates.
6319 
6320   The grid coordinates are across the entire grid, not just the local portion
6321 
6322   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6323   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6324   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6325   `DM_BOUNDARY_PERIODIC` boundary type.
6326 
6327   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
6328   a single value per point) you can skip filling those indices.
6329 
6330   Fortran Note:
6331   `idxm` and `idxn` should be declared as
6332 $     MatStencil idxm(4, m)
6333   and the values inserted using
6334 .vb
6335     idxm(MatStencil_i, 1) = i
6336     idxm(MatStencil_j, 1) = j
6337     idxm(MatStencil_k, 1) = k
6338     idxm(MatStencil_c, 1) = c
6339    etc
6340 .ve
6341 
6342 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6343           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6344 @*/
6345 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6346 {
6347   PetscInt  dim    = mat->stencil.dim;
6348   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6349   PetscInt *dims   = mat->stencil.dims + 1;
6350   PetscInt *starts = mat->stencil.starts;
6351   PetscInt *dxm    = (PetscInt *)rows;
6352   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6353 
6354   PetscFunctionBegin;
6355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6356   PetscValidType(mat, 1);
6357   if (numRows) PetscAssertPointer(rows, 3);
6358 
6359   PetscCall(PetscMalloc1(numRows, &jdxm));
6360   for (i = 0; i < numRows; ++i) {
6361     /* Skip unused dimensions (they are ordered k, j, i, c) */
6362     for (j = 0; j < 3 - sdim; ++j) dxm++;
6363     /* Local index in X dir */
6364     tmp = *dxm++ - starts[0];
6365     /* Loop over remaining dimensions */
6366     for (j = 0; j < dim - 1; ++j) {
6367       /* If nonlocal, set index to be negative */
6368       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6369       /* Update local index */
6370       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6371     }
6372     /* Skip component slot if necessary */
6373     if (mat->stencil.noc) dxm++;
6374     /* Local row number */
6375     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6376   }
6377   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6378   PetscCall(PetscFree(jdxm));
6379   PetscFunctionReturn(PETSC_SUCCESS);
6380 }
6381 
6382 /*@
6383   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6384   of a set of rows and columns of a matrix.
6385 
6386   Collective
6387 
6388   Input Parameters:
6389 + mat     - the matrix
6390 . numRows - the number of rows/columns to remove
6391 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6392 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6393 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6394 - b       - optional vector of right hand side, that will be adjusted by provided solution
6395 
6396   Level: intermediate
6397 
6398   Notes:
6399   See `MatZeroRowsColumns()` for details on how this routine operates.
6400 
6401   The grid coordinates are across the entire grid, not just the local portion
6402 
6403   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6404   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6405   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6406   `DM_BOUNDARY_PERIODIC` boundary type.
6407 
6408   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
6409   a single value per point) you can skip filling those indices.
6410 
6411   Fortran Note:
6412   `idxm` and `idxn` should be declared as
6413 $     MatStencil idxm(4, m)
6414   and the values inserted using
6415 .vb
6416     idxm(MatStencil_i, 1) = i
6417     idxm(MatStencil_j, 1) = j
6418     idxm(MatStencil_k, 1) = k
6419     idxm(MatStencil_c, 1) = c
6420     etc
6421 .ve
6422 
6423 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6424           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6425 @*/
6426 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6427 {
6428   PetscInt  dim    = mat->stencil.dim;
6429   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6430   PetscInt *dims   = mat->stencil.dims + 1;
6431   PetscInt *starts = mat->stencil.starts;
6432   PetscInt *dxm    = (PetscInt *)rows;
6433   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6434 
6435   PetscFunctionBegin;
6436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6437   PetscValidType(mat, 1);
6438   if (numRows) PetscAssertPointer(rows, 3);
6439 
6440   PetscCall(PetscMalloc1(numRows, &jdxm));
6441   for (i = 0; i < numRows; ++i) {
6442     /* Skip unused dimensions (they are ordered k, j, i, c) */
6443     for (j = 0; j < 3 - sdim; ++j) dxm++;
6444     /* Local index in X dir */
6445     tmp = *dxm++ - starts[0];
6446     /* Loop over remaining dimensions */
6447     for (j = 0; j < dim - 1; ++j) {
6448       /* If nonlocal, set index to be negative */
6449       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6450       /* Update local index */
6451       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6452     }
6453     /* Skip component slot if necessary */
6454     if (mat->stencil.noc) dxm++;
6455     /* Local row number */
6456     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6457   }
6458   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6459   PetscCall(PetscFree(jdxm));
6460   PetscFunctionReturn(PETSC_SUCCESS);
6461 }
6462 
6463 /*@C
6464   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6465   of a set of rows of a matrix; using local numbering of rows.
6466 
6467   Collective
6468 
6469   Input Parameters:
6470 + mat     - the matrix
6471 . numRows - the number of rows to remove
6472 . rows    - the local row indices
6473 . diag    - value put in all diagonals of eliminated rows
6474 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6475 - b       - optional vector of right hand side, that will be adjusted by provided solution
6476 
6477   Level: intermediate
6478 
6479   Notes:
6480   Before calling `MatZeroRowsLocal()`, the user must first set the
6481   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6482 
6483   See `MatZeroRows()` for details on how this routine operates.
6484 
6485 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6486           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6487 @*/
6488 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6489 {
6490   PetscFunctionBegin;
6491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6492   PetscValidType(mat, 1);
6493   if (numRows) PetscAssertPointer(rows, 3);
6494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6496   MatCheckPreallocated(mat, 1);
6497 
6498   if (mat->ops->zerorowslocal) {
6499     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6500   } else {
6501     IS              is, newis;
6502     const PetscInt *newRows;
6503 
6504     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6505     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6506     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6507     PetscCall(ISGetIndices(newis, &newRows));
6508     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6509     PetscCall(ISRestoreIndices(newis, &newRows));
6510     PetscCall(ISDestroy(&newis));
6511     PetscCall(ISDestroy(&is));
6512   }
6513   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6514   PetscFunctionReturn(PETSC_SUCCESS);
6515 }
6516 
6517 /*@
6518   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6519   of a set of rows of a matrix; using local numbering of rows.
6520 
6521   Collective
6522 
6523   Input Parameters:
6524 + mat  - the matrix
6525 . is   - index set of rows to remove
6526 . diag - value put in all diagonals of eliminated rows
6527 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6528 - b    - optional vector of right hand side, that will be adjusted by provided solution
6529 
6530   Level: intermediate
6531 
6532   Notes:
6533   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6534   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6535 
6536   See `MatZeroRows()` for details on how this routine operates.
6537 
6538 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6539           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6540 @*/
6541 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6542 {
6543   PetscInt        numRows;
6544   const PetscInt *rows;
6545 
6546   PetscFunctionBegin;
6547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6548   PetscValidType(mat, 1);
6549   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6550   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6551   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6552   MatCheckPreallocated(mat, 1);
6553 
6554   PetscCall(ISGetLocalSize(is, &numRows));
6555   PetscCall(ISGetIndices(is, &rows));
6556   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6557   PetscCall(ISRestoreIndices(is, &rows));
6558   PetscFunctionReturn(PETSC_SUCCESS);
6559 }
6560 
6561 /*@
6562   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6563   of a set of rows and columns of a matrix; using local numbering of rows.
6564 
6565   Collective
6566 
6567   Input Parameters:
6568 + mat     - the matrix
6569 . numRows - the number of rows to remove
6570 . rows    - the global row indices
6571 . diag    - value put in all diagonals of eliminated rows
6572 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6573 - b       - optional vector of right hand side, that will be adjusted by provided solution
6574 
6575   Level: intermediate
6576 
6577   Notes:
6578   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6579   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6580 
6581   See `MatZeroRowsColumns()` for details on how this routine operates.
6582 
6583 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6584           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6585 @*/
6586 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6587 {
6588   IS              is, newis;
6589   const PetscInt *newRows;
6590 
6591   PetscFunctionBegin;
6592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6593   PetscValidType(mat, 1);
6594   if (numRows) PetscAssertPointer(rows, 3);
6595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6597   MatCheckPreallocated(mat, 1);
6598 
6599   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6600   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6601   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6602   PetscCall(ISGetIndices(newis, &newRows));
6603   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6604   PetscCall(ISRestoreIndices(newis, &newRows));
6605   PetscCall(ISDestroy(&newis));
6606   PetscCall(ISDestroy(&is));
6607   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6608   PetscFunctionReturn(PETSC_SUCCESS);
6609 }
6610 
6611 /*@
6612   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6613   of a set of rows and columns of a matrix; using local numbering of rows.
6614 
6615   Collective
6616 
6617   Input Parameters:
6618 + mat  - the matrix
6619 . is   - index set of rows to remove
6620 . diag - value put in all diagonals of eliminated rows
6621 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6622 - b    - optional vector of right hand side, that will be adjusted by provided solution
6623 
6624   Level: intermediate
6625 
6626   Notes:
6627   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6628   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6629 
6630   See `MatZeroRowsColumns()` for details on how this routine operates.
6631 
6632 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6633           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6634 @*/
6635 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6636 {
6637   PetscInt        numRows;
6638   const PetscInt *rows;
6639 
6640   PetscFunctionBegin;
6641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6642   PetscValidType(mat, 1);
6643   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6646   MatCheckPreallocated(mat, 1);
6647 
6648   PetscCall(ISGetLocalSize(is, &numRows));
6649   PetscCall(ISGetIndices(is, &rows));
6650   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6651   PetscCall(ISRestoreIndices(is, &rows));
6652   PetscFunctionReturn(PETSC_SUCCESS);
6653 }
6654 
6655 /*@C
6656   MatGetSize - Returns the numbers of rows and columns in a matrix.
6657 
6658   Not Collective
6659 
6660   Input Parameter:
6661 . mat - the matrix
6662 
6663   Output Parameters:
6664 + m - the number of global rows
6665 - n - the number of global columns
6666 
6667   Level: beginner
6668 
6669   Note:
6670   Both output parameters can be `NULL` on input.
6671 
6672 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6673 @*/
6674 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6675 {
6676   PetscFunctionBegin;
6677   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6678   if (m) *m = mat->rmap->N;
6679   if (n) *n = mat->cmap->N;
6680   PetscFunctionReturn(PETSC_SUCCESS);
6681 }
6682 
6683 /*@C
6684   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6685   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6686 
6687   Not Collective
6688 
6689   Input Parameter:
6690 . mat - the matrix
6691 
6692   Output Parameters:
6693 + m - the number of local rows, use `NULL` to not obtain this value
6694 - n - the number of local columns, use `NULL` to not obtain this value
6695 
6696   Level: beginner
6697 
6698 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6699 @*/
6700 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6701 {
6702   PetscFunctionBegin;
6703   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6704   if (m) PetscAssertPointer(m, 2);
6705   if (n) PetscAssertPointer(n, 3);
6706   if (m) *m = mat->rmap->n;
6707   if (n) *n = mat->cmap->n;
6708   PetscFunctionReturn(PETSC_SUCCESS);
6709 }
6710 
6711 /*@C
6712   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6713   vector one multiplies this matrix by that are owned by this processor.
6714 
6715   Not Collective, unless matrix has not been allocated, then collective
6716 
6717   Input Parameter:
6718 . mat - the matrix
6719 
6720   Output Parameters:
6721 + m - the global index of the first local column, use `NULL` to not obtain this value
6722 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6723 
6724   Level: developer
6725 
6726   Note:
6727   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6728   Layouts](sec_matlayout) for details on matrix layouts.
6729 
6730 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6731 @*/
6732 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6733 {
6734   PetscFunctionBegin;
6735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6736   PetscValidType(mat, 1);
6737   if (m) PetscAssertPointer(m, 2);
6738   if (n) PetscAssertPointer(n, 3);
6739   MatCheckPreallocated(mat, 1);
6740   if (m) *m = mat->cmap->rstart;
6741   if (n) *n = mat->cmap->rend;
6742   PetscFunctionReturn(PETSC_SUCCESS);
6743 }
6744 
6745 /*@C
6746   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6747   this MPI process.
6748 
6749   Not Collective
6750 
6751   Input Parameter:
6752 . mat - the matrix
6753 
6754   Output Parameters:
6755 + m - the global index of the first local row, use `NULL` to not obtain this value
6756 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6757 
6758   Level: beginner
6759 
6760   Note:
6761   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6762   would contain the result of a matrix vector product with this matrix. See [Matrix
6763   Layouts](sec_matlayout) for details on matrix layouts.
6764 
6765 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6766           `PetscLayout`
6767 @*/
6768 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6769 {
6770   PetscFunctionBegin;
6771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6772   PetscValidType(mat, 1);
6773   if (m) PetscAssertPointer(m, 2);
6774   if (n) PetscAssertPointer(n, 3);
6775   MatCheckPreallocated(mat, 1);
6776   if (m) *m = mat->rmap->rstart;
6777   if (n) *n = mat->rmap->rend;
6778   PetscFunctionReturn(PETSC_SUCCESS);
6779 }
6780 
6781 /*@C
6782   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6783   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6784 
6785   Not Collective, unless matrix has not been allocated
6786 
6787   Input Parameter:
6788 . mat - the matrix
6789 
6790   Output Parameter:
6791 . ranges - start of each processors portion plus one more than the total length at the end
6792 
6793   Level: beginner
6794 
6795   Note:
6796   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6797   would contain the result of a matrix vector product with this matrix. See [Matrix
6798   Layouts](sec_matlayout) for details on matrix layouts.
6799 
6800 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6801 @*/
6802 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6803 {
6804   PetscFunctionBegin;
6805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6806   PetscValidType(mat, 1);
6807   MatCheckPreallocated(mat, 1);
6808   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6809   PetscFunctionReturn(PETSC_SUCCESS);
6810 }
6811 
6812 /*@C
6813   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6814   vector one multiplies this vector by that are owned by each processor.
6815 
6816   Not Collective, unless matrix has not been allocated
6817 
6818   Input Parameter:
6819 . mat - the matrix
6820 
6821   Output Parameter:
6822 . ranges - start of each processors portion plus one more than the total length at the end
6823 
6824   Level: beginner
6825 
6826   Note:
6827   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6828   Layouts](sec_matlayout) for details on matrix layouts.
6829 
6830 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6831 @*/
6832 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6833 {
6834   PetscFunctionBegin;
6835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6836   PetscValidType(mat, 1);
6837   MatCheckPreallocated(mat, 1);
6838   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6839   PetscFunctionReturn(PETSC_SUCCESS);
6840 }
6841 
6842 /*@C
6843   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6844 
6845   Not Collective
6846 
6847   Input Parameter:
6848 . A - matrix
6849 
6850   Output Parameters:
6851 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6852 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6853 
6854   Level: intermediate
6855 
6856   Note:
6857   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6858   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6859   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6860   details on matrix layouts.
6861 
6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6863 @*/
6864 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6865 {
6866   PetscErrorCode (*f)(Mat, IS *, IS *);
6867 
6868   PetscFunctionBegin;
6869   MatCheckPreallocated(A, 1);
6870   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6871   if (f) {
6872     PetscCall((*f)(A, rows, cols));
6873   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6874     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6875     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6876   }
6877   PetscFunctionReturn(PETSC_SUCCESS);
6878 }
6879 
6880 /*@C
6881   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6882   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6883   to complete the factorization.
6884 
6885   Collective
6886 
6887   Input Parameters:
6888 + fact - the factorized matrix obtained with `MatGetFactor()`
6889 . mat  - the matrix
6890 . row  - row permutation
6891 . col  - column permutation
6892 - info - structure containing
6893 .vb
6894       levels - number of levels of fill.
6895       expected fill - as ratio of original fill.
6896       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6897                 missing diagonal entries)
6898 .ve
6899 
6900   Level: developer
6901 
6902   Notes:
6903   See [Matrix Factorization](sec_matfactor) for additional information.
6904 
6905   Most users should employ the `KSP` interface for linear solvers
6906   instead of working directly with matrix algebra routines such as this.
6907   See, e.g., `KSPCreate()`.
6908 
6909   Uses the definition of level of fill as in Y. Saad, 2003
6910 
6911   Developer Note:
6912   The Fortran interface is not autogenerated as the
6913   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6914 
6915   References:
6916 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6917 
6918 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6919           `MatGetOrdering()`, `MatFactorInfo`
6920 @*/
6921 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6922 {
6923   PetscFunctionBegin;
6924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6925   PetscValidType(mat, 2);
6926   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6927   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6928   PetscAssertPointer(info, 5);
6929   PetscAssertPointer(fact, 1);
6930   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6931   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6932   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6933   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6934   MatCheckPreallocated(mat, 2);
6935 
6936   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6937   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6938   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6939   PetscFunctionReturn(PETSC_SUCCESS);
6940 }
6941 
6942 /*@C
6943   MatICCFactorSymbolic - Performs symbolic incomplete
6944   Cholesky factorization for a symmetric matrix.  Use
6945   `MatCholeskyFactorNumeric()` to complete the factorization.
6946 
6947   Collective
6948 
6949   Input Parameters:
6950 + fact - the factorized matrix obtained with `MatGetFactor()`
6951 . mat  - the matrix to be factored
6952 . perm - row and column permutation
6953 - info - structure containing
6954 .vb
6955       levels - number of levels of fill.
6956       expected fill - as ratio of original fill.
6957 .ve
6958 
6959   Level: developer
6960 
6961   Notes:
6962   Most users should employ the `KSP` interface for linear solvers
6963   instead of working directly with matrix algebra routines such as this.
6964   See, e.g., `KSPCreate()`.
6965 
6966   This uses the definition of level of fill as in Y. Saad, 2003
6967 
6968   Developer Note:
6969   The Fortran interface is not autogenerated as the
6970   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6971 
6972   References:
6973 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6974 
6975 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6976 @*/
6977 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6978 {
6979   PetscFunctionBegin;
6980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6981   PetscValidType(mat, 2);
6982   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6983   PetscAssertPointer(info, 4);
6984   PetscAssertPointer(fact, 1);
6985   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6986   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6987   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6988   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6989   MatCheckPreallocated(mat, 2);
6990 
6991   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6992   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6993   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6994   PetscFunctionReturn(PETSC_SUCCESS);
6995 }
6996 
6997 /*@C
6998   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6999   points to an array of valid matrices, they may be reused to store the new
7000   submatrices.
7001 
7002   Collective
7003 
7004   Input Parameters:
7005 + mat   - the matrix
7006 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7007 . irow  - index set of rows to extract
7008 . icol  - index set of columns to extract
7009 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7010 
7011   Output Parameter:
7012 . submat - the array of submatrices
7013 
7014   Level: advanced
7015 
7016   Notes:
7017   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7018   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7019   to extract a parallel submatrix.
7020 
7021   Some matrix types place restrictions on the row and column
7022   indices, such as that they be sorted or that they be equal to each other.
7023 
7024   The index sets may not have duplicate entries.
7025 
7026   When extracting submatrices from a parallel matrix, each processor can
7027   form a different submatrix by setting the rows and columns of its
7028   individual index sets according to the local submatrix desired.
7029 
7030   When finished using the submatrices, the user should destroy
7031   them with `MatDestroySubMatrices()`.
7032 
7033   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7034   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7035 
7036   This routine creates the matrices in submat; you should NOT create them before
7037   calling it. It also allocates the array of matrix pointers submat.
7038 
7039   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7040   request one row/column in a block, they must request all rows/columns that are in
7041   that block. For example, if the block size is 2 you cannot request just row 0 and
7042   column 0.
7043 
7044   Fortran Note:
7045   The Fortran interface is slightly different from that given below; it
7046   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7047 
7048 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7049 @*/
7050 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7051 {
7052   PetscInt  i;
7053   PetscBool eq;
7054 
7055   PetscFunctionBegin;
7056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7057   PetscValidType(mat, 1);
7058   if (n) {
7059     PetscAssertPointer(irow, 3);
7060     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7061     PetscAssertPointer(icol, 4);
7062     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7063   }
7064   PetscAssertPointer(submat, 6);
7065   if (n && scall == MAT_REUSE_MATRIX) {
7066     PetscAssertPointer(*submat, 6);
7067     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7068   }
7069   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7070   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7071   MatCheckPreallocated(mat, 1);
7072   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7073   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7074   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7075   for (i = 0; i < n; i++) {
7076     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7077     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7078     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7079 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7080     if (mat->boundtocpu && mat->bindingpropagates) {
7081       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7082       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7083     }
7084 #endif
7085   }
7086   PetscFunctionReturn(PETSC_SUCCESS);
7087 }
7088 
7089 /*@C
7090   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7091 
7092   Collective
7093 
7094   Input Parameters:
7095 + mat   - the matrix
7096 . n     - the number of submatrixes to be extracted
7097 . irow  - index set of rows to extract
7098 . icol  - index set of columns to extract
7099 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7100 
7101   Output Parameter:
7102 . submat - the array of submatrices
7103 
7104   Level: advanced
7105 
7106   Note:
7107   This is used by `PCGASM`
7108 
7109 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7110 @*/
7111 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7112 {
7113   PetscInt  i;
7114   PetscBool eq;
7115 
7116   PetscFunctionBegin;
7117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7118   PetscValidType(mat, 1);
7119   if (n) {
7120     PetscAssertPointer(irow, 3);
7121     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7122     PetscAssertPointer(icol, 4);
7123     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7124   }
7125   PetscAssertPointer(submat, 6);
7126   if (n && scall == MAT_REUSE_MATRIX) {
7127     PetscAssertPointer(*submat, 6);
7128     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7129   }
7130   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7131   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7132   MatCheckPreallocated(mat, 1);
7133 
7134   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7135   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7136   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7137   for (i = 0; i < n; i++) {
7138     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7139     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7140   }
7141   PetscFunctionReturn(PETSC_SUCCESS);
7142 }
7143 
7144 /*@C
7145   MatDestroyMatrices - Destroys an array of matrices.
7146 
7147   Collective
7148 
7149   Input Parameters:
7150 + n   - the number of local matrices
7151 - mat - the matrices (this is a pointer to the array of matrices)
7152 
7153   Level: advanced
7154 
7155   Note:
7156   Frees not only the matrices, but also the array that contains the matrices
7157 
7158   Fortran Note:
7159   This does not free the array.
7160 
7161 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7162 @*/
7163 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7164 {
7165   PetscInt i;
7166 
7167   PetscFunctionBegin;
7168   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7169   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7170   PetscAssertPointer(mat, 2);
7171 
7172   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7173 
7174   /* memory is allocated even if n = 0 */
7175   PetscCall(PetscFree(*mat));
7176   PetscFunctionReturn(PETSC_SUCCESS);
7177 }
7178 
7179 /*@C
7180   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7181 
7182   Collective
7183 
7184   Input Parameters:
7185 + n   - the number of local matrices
7186 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7187                        sequence of `MatCreateSubMatrices()`)
7188 
7189   Level: advanced
7190 
7191   Note:
7192   Frees not only the matrices, but also the array that contains the matrices
7193 
7194   Fortran Note:
7195   This does not free the array.
7196 
7197 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7198 @*/
7199 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7200 {
7201   Mat mat0;
7202 
7203   PetscFunctionBegin;
7204   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7205   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7206   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7207   PetscAssertPointer(mat, 2);
7208 
7209   mat0 = (*mat)[0];
7210   if (mat0 && mat0->ops->destroysubmatrices) {
7211     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7212   } else {
7213     PetscCall(MatDestroyMatrices(n, mat));
7214   }
7215   PetscFunctionReturn(PETSC_SUCCESS);
7216 }
7217 
7218 /*@C
7219   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7220 
7221   Collective
7222 
7223   Input Parameter:
7224 . mat - the matrix
7225 
7226   Output Parameter:
7227 . matstruct - the sequential matrix with the nonzero structure of mat
7228 
7229   Level: developer
7230 
7231 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7232 @*/
7233 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7234 {
7235   PetscFunctionBegin;
7236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7237   PetscAssertPointer(matstruct, 2);
7238 
7239   PetscValidType(mat, 1);
7240   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7241   MatCheckPreallocated(mat, 1);
7242 
7243   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7244   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7245   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7246   PetscFunctionReturn(PETSC_SUCCESS);
7247 }
7248 
7249 /*@C
7250   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7251 
7252   Collective
7253 
7254   Input Parameter:
7255 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7256                        sequence of `MatGetSeqNonzeroStructure()`)
7257 
7258   Level: advanced
7259 
7260   Note:
7261   Frees not only the matrices, but also the array that contains the matrices
7262 
7263 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7264 @*/
7265 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7266 {
7267   PetscFunctionBegin;
7268   PetscAssertPointer(mat, 1);
7269   PetscCall(MatDestroy(mat));
7270   PetscFunctionReturn(PETSC_SUCCESS);
7271 }
7272 
7273 /*@
7274   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7275   replaces the index sets by larger ones that represent submatrices with
7276   additional overlap.
7277 
7278   Collective
7279 
7280   Input Parameters:
7281 + mat - the matrix
7282 . n   - the number of index sets
7283 . is  - the array of index sets (these index sets will changed during the call)
7284 - ov  - the additional overlap requested
7285 
7286   Options Database Key:
7287 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7288 
7289   Level: developer
7290 
7291   Note:
7292   The computed overlap preserves the matrix block sizes when the blocks are square.
7293   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7294   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7295 
7296 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7297 @*/
7298 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7299 {
7300   PetscInt i, bs, cbs;
7301 
7302   PetscFunctionBegin;
7303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7304   PetscValidType(mat, 1);
7305   PetscValidLogicalCollectiveInt(mat, n, 2);
7306   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7307   if (n) {
7308     PetscAssertPointer(is, 3);
7309     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7310   }
7311   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7312   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7313   MatCheckPreallocated(mat, 1);
7314 
7315   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7316   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7317   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7318   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7319   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7320   if (bs == cbs) {
7321     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7322   }
7323   PetscFunctionReturn(PETSC_SUCCESS);
7324 }
7325 
7326 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7327 
7328 /*@
7329   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7330   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7331   additional overlap.
7332 
7333   Collective
7334 
7335   Input Parameters:
7336 + mat - the matrix
7337 . n   - the number of index sets
7338 . is  - the array of index sets (these index sets will changed during the call)
7339 - ov  - the additional overlap requested
7340 
7341   `   Options Database Key:
7342 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7343 
7344   Level: developer
7345 
7346 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7347 @*/
7348 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7349 {
7350   PetscInt i;
7351 
7352   PetscFunctionBegin;
7353   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7354   PetscValidType(mat, 1);
7355   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7356   if (n) {
7357     PetscAssertPointer(is, 3);
7358     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7359   }
7360   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7361   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7362   MatCheckPreallocated(mat, 1);
7363   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7364   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7365   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7366   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7367   PetscFunctionReturn(PETSC_SUCCESS);
7368 }
7369 
7370 /*@
7371   MatGetBlockSize - Returns the matrix block size.
7372 
7373   Not Collective
7374 
7375   Input Parameter:
7376 . mat - the matrix
7377 
7378   Output Parameter:
7379 . bs - block size
7380 
7381   Level: intermediate
7382 
7383   Notes:
7384   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7385 
7386   If the block size has not been set yet this routine returns 1.
7387 
7388 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7389 @*/
7390 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7391 {
7392   PetscFunctionBegin;
7393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7394   PetscAssertPointer(bs, 2);
7395   *bs = PetscAbs(mat->rmap->bs);
7396   PetscFunctionReturn(PETSC_SUCCESS);
7397 }
7398 
7399 /*@
7400   MatGetBlockSizes - Returns the matrix block row and column sizes.
7401 
7402   Not Collective
7403 
7404   Input Parameter:
7405 . mat - the matrix
7406 
7407   Output Parameters:
7408 + rbs - row block size
7409 - cbs - column block size
7410 
7411   Level: intermediate
7412 
7413   Notes:
7414   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7415   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7416 
7417   If a block size has not been set yet this routine returns 1.
7418 
7419 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7420 @*/
7421 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7422 {
7423   PetscFunctionBegin;
7424   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7425   if (rbs) PetscAssertPointer(rbs, 2);
7426   if (cbs) PetscAssertPointer(cbs, 3);
7427   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7428   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7429   PetscFunctionReturn(PETSC_SUCCESS);
7430 }
7431 
7432 /*@
7433   MatSetBlockSize - Sets the matrix block size.
7434 
7435   Logically Collective
7436 
7437   Input Parameters:
7438 + mat - the matrix
7439 - bs  - block size
7440 
7441   Level: intermediate
7442 
7443   Notes:
7444   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7445   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7446 
7447   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7448   is compatible with the matrix local sizes.
7449 
7450 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7451 @*/
7452 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7453 {
7454   PetscFunctionBegin;
7455   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7456   PetscValidLogicalCollectiveInt(mat, bs, 2);
7457   PetscCall(MatSetBlockSizes(mat, bs, bs));
7458   PetscFunctionReturn(PETSC_SUCCESS);
7459 }
7460 
7461 typedef struct {
7462   PetscInt         n;
7463   IS              *is;
7464   Mat             *mat;
7465   PetscObjectState nonzerostate;
7466   Mat              C;
7467 } EnvelopeData;
7468 
7469 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7470 {
7471   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7472   PetscCall(PetscFree(edata->is));
7473   PetscCall(PetscFree(edata));
7474   return PETSC_SUCCESS;
7475 }
7476 
7477 /*@
7478   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7479   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7480 
7481   Collective
7482 
7483   Input Parameter:
7484 . mat - the matrix
7485 
7486   Level: intermediate
7487 
7488   Notes:
7489   There can be zeros within the blocks
7490 
7491   The blocks can overlap between processes, including laying on more than two processes
7492 
7493 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7494 @*/
7495 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7496 {
7497   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7498   PetscInt          *diag, *odiag, sc;
7499   VecScatter         scatter;
7500   PetscScalar       *seqv;
7501   const PetscScalar *parv;
7502   const PetscInt    *ia, *ja;
7503   PetscBool          set, flag, done;
7504   Mat                AA = mat, A;
7505   MPI_Comm           comm;
7506   PetscMPIInt        rank, size, tag;
7507   MPI_Status         status;
7508   PetscContainer     container;
7509   EnvelopeData      *edata;
7510   Vec                seq, par;
7511   IS                 isglobal;
7512 
7513   PetscFunctionBegin;
7514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7515   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7516   if (!set || !flag) {
7517     /* TODO: only needs nonzero structure of transpose */
7518     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7519     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7520   }
7521   PetscCall(MatAIJGetLocalMat(AA, &A));
7522   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7523   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7524 
7525   PetscCall(MatGetLocalSize(mat, &n, NULL));
7526   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7527   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7528   PetscCallMPI(MPI_Comm_size(comm, &size));
7529   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7530 
7531   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7532 
7533   if (rank > 0) {
7534     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7535     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7536   }
7537   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7538   for (i = 0; i < n; i++) {
7539     env = PetscMax(env, ja[ia[i + 1] - 1]);
7540     II  = rstart + i;
7541     if (env == II) {
7542       starts[lblocks]  = tbs;
7543       sizes[lblocks++] = 1 + II - tbs;
7544       tbs              = 1 + II;
7545     }
7546   }
7547   if (rank < size - 1) {
7548     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7549     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7550   }
7551 
7552   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7553   if (!set || !flag) PetscCall(MatDestroy(&AA));
7554   PetscCall(MatDestroy(&A));
7555 
7556   PetscCall(PetscNew(&edata));
7557   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7558   edata->n = lblocks;
7559   /* create IS needed for extracting blocks from the original matrix */
7560   PetscCall(PetscMalloc1(lblocks, &edata->is));
7561   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7562 
7563   /* Create the resulting inverse matrix structure with preallocation information */
7564   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7565   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7566   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7567   PetscCall(MatSetType(edata->C, MATAIJ));
7568 
7569   /* Communicate the start and end of each row, from each block to the correct rank */
7570   /* TODO: Use PetscSF instead of VecScatter */
7571   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7572   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7573   PetscCall(VecGetArrayWrite(seq, &seqv));
7574   for (PetscInt i = 0; i < lblocks; i++) {
7575     for (PetscInt j = 0; j < sizes[i]; j++) {
7576       seqv[cnt]     = starts[i];
7577       seqv[cnt + 1] = starts[i] + sizes[i];
7578       cnt += 2;
7579     }
7580   }
7581   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7582   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7583   sc -= cnt;
7584   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7585   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7586   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7587   PetscCall(ISDestroy(&isglobal));
7588   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7589   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7590   PetscCall(VecScatterDestroy(&scatter));
7591   PetscCall(VecDestroy(&seq));
7592   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7593   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7594   PetscCall(VecGetArrayRead(par, &parv));
7595   cnt = 0;
7596   PetscCall(MatGetSize(mat, NULL, &n));
7597   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7598     PetscInt start, end, d = 0, od = 0;
7599 
7600     start = (PetscInt)PetscRealPart(parv[cnt]);
7601     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7602     cnt += 2;
7603 
7604     if (start < cstart) {
7605       od += cstart - start + n - cend;
7606       d += cend - cstart;
7607     } else if (start < cend) {
7608       od += n - cend;
7609       d += cend - start;
7610     } else od += n - start;
7611     if (end <= cstart) {
7612       od -= cstart - end + n - cend;
7613       d -= cend - cstart;
7614     } else if (end < cend) {
7615       od -= n - cend;
7616       d -= cend - end;
7617     } else od -= n - end;
7618 
7619     odiag[i] = od;
7620     diag[i]  = d;
7621   }
7622   PetscCall(VecRestoreArrayRead(par, &parv));
7623   PetscCall(VecDestroy(&par));
7624   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7625   PetscCall(PetscFree2(diag, odiag));
7626   PetscCall(PetscFree2(sizes, starts));
7627 
7628   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7629   PetscCall(PetscContainerSetPointer(container, edata));
7630   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7631   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7632   PetscCall(PetscObjectDereference((PetscObject)container));
7633   PetscFunctionReturn(PETSC_SUCCESS);
7634 }
7635 
7636 /*@
7637   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7638 
7639   Collective
7640 
7641   Input Parameters:
7642 + A     - the matrix
7643 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7644 
7645   Output Parameter:
7646 . C - matrix with inverted block diagonal of `A`
7647 
7648   Level: advanced
7649 
7650   Note:
7651   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7652 
7653 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7654 @*/
7655 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7656 {
7657   PetscContainer   container;
7658   EnvelopeData    *edata;
7659   PetscObjectState nonzerostate;
7660 
7661   PetscFunctionBegin;
7662   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7663   if (!container) {
7664     PetscCall(MatComputeVariableBlockEnvelope(A));
7665     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7666   }
7667   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7668   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7669   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7670   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7671 
7672   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7673   *C = edata->C;
7674 
7675   for (PetscInt i = 0; i < edata->n; i++) {
7676     Mat          D;
7677     PetscScalar *dvalues;
7678 
7679     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7680     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7681     PetscCall(MatSeqDenseInvert(D));
7682     PetscCall(MatDenseGetArray(D, &dvalues));
7683     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7684     PetscCall(MatDestroy(&D));
7685   }
7686   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7687   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7688   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7689   PetscFunctionReturn(PETSC_SUCCESS);
7690 }
7691 
7692 /*@
7693   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7694 
7695   Logically Collective
7696 
7697   Input Parameters:
7698 + mat     - the matrix
7699 . nblocks - the number of blocks on this process, each block can only exist on a single process
7700 - bsizes  - the block sizes
7701 
7702   Level: intermediate
7703 
7704   Notes:
7705   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7706 
7707   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.
7708 
7709 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7710           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7711 @*/
7712 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7713 {
7714   PetscInt i, ncnt = 0, nlocal;
7715 
7716   PetscFunctionBegin;
7717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7718   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7719   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7720   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7721   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);
7722   PetscCall(PetscFree(mat->bsizes));
7723   mat->nblocks = nblocks;
7724   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7725   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7726   PetscFunctionReturn(PETSC_SUCCESS);
7727 }
7728 
7729 /*@C
7730   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7731 
7732   Logically Collective; No Fortran Support
7733 
7734   Input Parameter:
7735 . mat - the matrix
7736 
7737   Output Parameters:
7738 + nblocks - the number of blocks on this process
7739 - bsizes  - the block sizes
7740 
7741   Level: intermediate
7742 
7743 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7744 @*/
7745 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7746 {
7747   PetscFunctionBegin;
7748   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7749   *nblocks = mat->nblocks;
7750   *bsizes  = mat->bsizes;
7751   PetscFunctionReturn(PETSC_SUCCESS);
7752 }
7753 
7754 /*@
7755   MatSetBlockSizes - Sets the matrix block row and column sizes.
7756 
7757   Logically Collective
7758 
7759   Input Parameters:
7760 + mat - the matrix
7761 . rbs - row block size
7762 - cbs - column block size
7763 
7764   Level: intermediate
7765 
7766   Notes:
7767   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7768   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7769   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7770 
7771   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7772   are compatible with the matrix local sizes.
7773 
7774   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7775 
7776 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7777 @*/
7778 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7779 {
7780   PetscFunctionBegin;
7781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7782   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7783   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7784   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7785   if (mat->rmap->refcnt) {
7786     ISLocalToGlobalMapping l2g  = NULL;
7787     PetscLayout            nmap = NULL;
7788 
7789     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7790     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7791     PetscCall(PetscLayoutDestroy(&mat->rmap));
7792     mat->rmap          = nmap;
7793     mat->rmap->mapping = l2g;
7794   }
7795   if (mat->cmap->refcnt) {
7796     ISLocalToGlobalMapping l2g  = NULL;
7797     PetscLayout            nmap = NULL;
7798 
7799     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7800     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7801     PetscCall(PetscLayoutDestroy(&mat->cmap));
7802     mat->cmap          = nmap;
7803     mat->cmap->mapping = l2g;
7804   }
7805   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7806   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7807   PetscFunctionReturn(PETSC_SUCCESS);
7808 }
7809 
7810 /*@
7811   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7812 
7813   Logically Collective
7814 
7815   Input Parameters:
7816 + mat     - the matrix
7817 . fromRow - matrix from which to copy row block size
7818 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7819 
7820   Level: developer
7821 
7822 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7823 @*/
7824 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7825 {
7826   PetscFunctionBegin;
7827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7828   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7829   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7830   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7831   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7832   PetscFunctionReturn(PETSC_SUCCESS);
7833 }
7834 
7835 /*@
7836   MatResidual - Default routine to calculate the residual r = b - Ax
7837 
7838   Collective
7839 
7840   Input Parameters:
7841 + mat - the matrix
7842 . b   - the right-hand-side
7843 - x   - the approximate solution
7844 
7845   Output Parameter:
7846 . r - location to store the residual
7847 
7848   Level: developer
7849 
7850 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7851 @*/
7852 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7853 {
7854   PetscFunctionBegin;
7855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7856   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7857   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7858   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7859   PetscValidType(mat, 1);
7860   MatCheckPreallocated(mat, 1);
7861   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7862   if (!mat->ops->residual) {
7863     PetscCall(MatMult(mat, x, r));
7864     PetscCall(VecAYPX(r, -1.0, b));
7865   } else {
7866     PetscUseTypeMethod(mat, residual, b, x, r);
7867   }
7868   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7869   PetscFunctionReturn(PETSC_SUCCESS);
7870 }
7871 
7872 /*MC
7873     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7874 
7875     Synopsis:
7876     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7877 
7878     Not Collective
7879 
7880     Input Parameters:
7881 +   A - the matrix
7882 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7883 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7884 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7885                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7886                  always used.
7887 
7888     Output Parameters:
7889 +   n - number of local rows in the (possibly compressed) matrix
7890 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7891 .   ja - the column indices
7892 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7893            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7894 
7895     Level: developer
7896 
7897     Note:
7898     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7899 
7900 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7901 M*/
7902 
7903 /*MC
7904     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7905 
7906     Synopsis:
7907     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7908 
7909     Not Collective
7910 
7911     Input Parameters:
7912 +   A - the  matrix
7913 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7914 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7915     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7916                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7917                  always used.
7918 .   n - number of local rows in the (possibly compressed) matrix
7919 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7920 .   ja - the column indices
7921 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7922            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7923 
7924     Level: developer
7925 
7926 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7927 M*/
7928 
7929 /*@C
7930   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7931 
7932   Collective
7933 
7934   Input Parameters:
7935 + mat             - the matrix
7936 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7937 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7938 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7939                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7940                  always used.
7941 
7942   Output Parameters:
7943 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7944 . 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
7945 . ja   - the column indices, use `NULL` if not needed
7946 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7947            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7948 
7949   Level: developer
7950 
7951   Notes:
7952   You CANNOT change any of the ia[] or ja[] values.
7953 
7954   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7955 
7956   Fortran Notes:
7957   Use
7958 .vb
7959     PetscInt, pointer :: ia(:),ja(:)
7960     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7961     ! Access the ith and jth entries via ia(i) and ja(j)
7962 .ve
7963 
7964   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7965 
7966 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7967 @*/
7968 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7969 {
7970   PetscFunctionBegin;
7971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7972   PetscValidType(mat, 1);
7973   if (n) PetscAssertPointer(n, 5);
7974   if (ia) PetscAssertPointer(ia, 6);
7975   if (ja) PetscAssertPointer(ja, 7);
7976   if (done) PetscAssertPointer(done, 8);
7977   MatCheckPreallocated(mat, 1);
7978   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7979   else {
7980     if (done) *done = PETSC_TRUE;
7981     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7982     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7983     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7984   }
7985   PetscFunctionReturn(PETSC_SUCCESS);
7986 }
7987 
7988 /*@C
7989   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7990 
7991   Collective
7992 
7993   Input Parameters:
7994 + mat             - the matrix
7995 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
7996 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7997                 symmetrized
7998 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7999                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8000                  always used.
8001 . n               - number of columns in the (possibly compressed) matrix
8002 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8003 - ja              - the row indices
8004 
8005   Output Parameter:
8006 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8007 
8008   Level: developer
8009 
8010 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8011 @*/
8012 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8013 {
8014   PetscFunctionBegin;
8015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8016   PetscValidType(mat, 1);
8017   PetscAssertPointer(n, 5);
8018   if (ia) PetscAssertPointer(ia, 6);
8019   if (ja) PetscAssertPointer(ja, 7);
8020   PetscAssertPointer(done, 8);
8021   MatCheckPreallocated(mat, 1);
8022   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8023   else {
8024     *done = PETSC_TRUE;
8025     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8026   }
8027   PetscFunctionReturn(PETSC_SUCCESS);
8028 }
8029 
8030 /*@C
8031   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8032 
8033   Collective
8034 
8035   Input Parameters:
8036 + mat             - the matrix
8037 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8038 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8039 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8040                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8041                  always used.
8042 . n               - size of (possibly compressed) matrix
8043 . ia              - the row pointers
8044 - ja              - the column indices
8045 
8046   Output Parameter:
8047 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8048 
8049   Level: developer
8050 
8051   Note:
8052   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8053   us of the array after it has been restored. If you pass `NULL`, it will
8054   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8055 
8056   Fortran Note:
8057   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8058 
8059 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8060 @*/
8061 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8062 {
8063   PetscFunctionBegin;
8064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8065   PetscValidType(mat, 1);
8066   if (ia) PetscAssertPointer(ia, 6);
8067   if (ja) PetscAssertPointer(ja, 7);
8068   if (done) PetscAssertPointer(done, 8);
8069   MatCheckPreallocated(mat, 1);
8070 
8071   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8072   else {
8073     if (done) *done = PETSC_TRUE;
8074     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8075     if (n) *n = 0;
8076     if (ia) *ia = NULL;
8077     if (ja) *ja = NULL;
8078   }
8079   PetscFunctionReturn(PETSC_SUCCESS);
8080 }
8081 
8082 /*@C
8083   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8084 
8085   Collective
8086 
8087   Input Parameters:
8088 + mat             - the matrix
8089 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8090 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8091 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8092                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8093                  always used.
8094 
8095   Output Parameters:
8096 + n    - size of (possibly compressed) matrix
8097 . ia   - the column pointers
8098 . ja   - the row indices
8099 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8100 
8101   Level: developer
8102 
8103 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8104 @*/
8105 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8106 {
8107   PetscFunctionBegin;
8108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8109   PetscValidType(mat, 1);
8110   if (ia) PetscAssertPointer(ia, 6);
8111   if (ja) PetscAssertPointer(ja, 7);
8112   PetscAssertPointer(done, 8);
8113   MatCheckPreallocated(mat, 1);
8114 
8115   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8116   else {
8117     *done = PETSC_TRUE;
8118     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8119     if (n) *n = 0;
8120     if (ia) *ia = NULL;
8121     if (ja) *ja = NULL;
8122   }
8123   PetscFunctionReturn(PETSC_SUCCESS);
8124 }
8125 
8126 /*@C
8127   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8128   `MatGetColumnIJ()`.
8129 
8130   Collective
8131 
8132   Input Parameters:
8133 + mat        - the matrix
8134 . ncolors    - maximum color value
8135 . n          - number of entries in colorarray
8136 - colorarray - array indicating color for each column
8137 
8138   Output Parameter:
8139 . iscoloring - coloring generated using colorarray information
8140 
8141   Level: developer
8142 
8143 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8144 @*/
8145 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8146 {
8147   PetscFunctionBegin;
8148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8149   PetscValidType(mat, 1);
8150   PetscAssertPointer(colorarray, 4);
8151   PetscAssertPointer(iscoloring, 5);
8152   MatCheckPreallocated(mat, 1);
8153 
8154   if (!mat->ops->coloringpatch) {
8155     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8156   } else {
8157     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8158   }
8159   PetscFunctionReturn(PETSC_SUCCESS);
8160 }
8161 
8162 /*@
8163   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8164 
8165   Logically Collective
8166 
8167   Input Parameter:
8168 . mat - the factored matrix to be reset
8169 
8170   Level: developer
8171 
8172   Notes:
8173   This routine should be used only with factored matrices formed by in-place
8174   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8175   format).  This option can save memory, for example, when solving nonlinear
8176   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8177   ILU(0) preconditioner.
8178 
8179   One can specify in-place ILU(0) factorization by calling
8180 .vb
8181      PCType(pc,PCILU);
8182      PCFactorSeUseInPlace(pc);
8183 .ve
8184   or by using the options -pc_type ilu -pc_factor_in_place
8185 
8186   In-place factorization ILU(0) can also be used as a local
8187   solver for the blocks within the block Jacobi or additive Schwarz
8188   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8189   for details on setting local solver options.
8190 
8191   Most users should employ the `KSP` interface for linear solvers
8192   instead of working directly with matrix algebra routines such as this.
8193   See, e.g., `KSPCreate()`.
8194 
8195 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8196 @*/
8197 PetscErrorCode MatSetUnfactored(Mat mat)
8198 {
8199   PetscFunctionBegin;
8200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8201   PetscValidType(mat, 1);
8202   MatCheckPreallocated(mat, 1);
8203   mat->factortype = MAT_FACTOR_NONE;
8204   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8205   PetscUseTypeMethod(mat, setunfactored);
8206   PetscFunctionReturn(PETSC_SUCCESS);
8207 }
8208 
8209 /*MC
8210     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8211 
8212     Synopsis:
8213     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8214 
8215     Not Collective
8216 
8217     Input Parameter:
8218 .   x - matrix
8219 
8220     Output Parameters:
8221 +   xx_v - the Fortran pointer to the array
8222 -   ierr - error code
8223 
8224     Example of Usage:
8225 .vb
8226       PetscScalar, pointer xx_v(:,:)
8227       ....
8228       call MatDenseGetArrayF90(x,xx_v,ierr)
8229       a = xx_v(3)
8230       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8231 .ve
8232 
8233     Level: advanced
8234 
8235 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8236 M*/
8237 
8238 /*MC
8239     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8240     accessed with `MatDenseGetArrayF90()`.
8241 
8242     Synopsis:
8243     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8244 
8245     Not Collective
8246 
8247     Input Parameters:
8248 +   x - matrix
8249 -   xx_v - the Fortran90 pointer to the array
8250 
8251     Output Parameter:
8252 .   ierr - error code
8253 
8254     Example of Usage:
8255 .vb
8256        PetscScalar, pointer xx_v(:,:)
8257        ....
8258        call MatDenseGetArrayF90(x,xx_v,ierr)
8259        a = xx_v(3)
8260        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8261 .ve
8262 
8263     Level: advanced
8264 
8265 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8266 M*/
8267 
8268 /*MC
8269     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8270 
8271     Synopsis:
8272     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8273 
8274     Not Collective
8275 
8276     Input Parameter:
8277 .   x - matrix
8278 
8279     Output Parameters:
8280 +   xx_v - the Fortran pointer to the array
8281 -   ierr - error code
8282 
8283     Example of Usage:
8284 .vb
8285       PetscScalar, pointer xx_v(:)
8286       ....
8287       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8288       a = xx_v(3)
8289       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8290 .ve
8291 
8292     Level: advanced
8293 
8294 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8295 M*/
8296 
8297 /*MC
8298     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8299     accessed with `MatSeqAIJGetArrayF90()`.
8300 
8301     Synopsis:
8302     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8303 
8304     Not Collective
8305 
8306     Input Parameters:
8307 +   x - matrix
8308 -   xx_v - the Fortran90 pointer to the array
8309 
8310     Output Parameter:
8311 .   ierr - error code
8312 
8313     Example of Usage:
8314 .vb
8315        PetscScalar, pointer xx_v(:)
8316        ....
8317        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8318        a = xx_v(3)
8319        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8320 .ve
8321 
8322     Level: advanced
8323 
8324 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8325 M*/
8326 
8327 /*@
8328   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8329   as the original matrix.
8330 
8331   Collective
8332 
8333   Input Parameters:
8334 + mat   - the original matrix
8335 . isrow - parallel `IS` containing the rows this processor should obtain
8336 . iscol - parallel `IS` containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8337 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8338 
8339   Output Parameter:
8340 . newmat - the new submatrix, of the same type as the original matrix
8341 
8342   Level: advanced
8343 
8344   Notes:
8345   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8346 
8347   Some matrix types place restrictions on the row and column indices, such
8348   as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8349   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8350 
8351   The index sets may not have duplicate entries.
8352 
8353   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8354   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8355   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8356   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8357   you are finished using it.
8358 
8359   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8360   the input matrix.
8361 
8362   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8363 
8364   Example usage:
8365   Consider the following 8x8 matrix with 34 non-zero values, that is
8366   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8367   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8368   as follows
8369 .vb
8370             1  2  0  |  0  3  0  |  0  4
8371     Proc0   0  5  6  |  7  0  0  |  8  0
8372             9  0 10  | 11  0  0  | 12  0
8373     -------------------------------------
8374            13  0 14  | 15 16 17  |  0  0
8375     Proc1   0 18  0  | 19 20 21  |  0  0
8376             0  0  0  | 22 23  0  | 24  0
8377     -------------------------------------
8378     Proc2  25 26 27  |  0  0 28  | 29  0
8379            30  0  0  | 31 32 33  |  0 34
8380 .ve
8381 
8382   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8383 
8384 .vb
8385             2  0  |  0  3  0  |  0
8386     Proc0   5  6  |  7  0  0  |  8
8387     -------------------------------
8388     Proc1  18  0  | 19 20 21  |  0
8389     -------------------------------
8390     Proc2  26 27  |  0  0 28  | 29
8391             0  0  | 31 32 33  |  0
8392 .ve
8393 
8394 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8395 @*/
8396 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8397 {
8398   PetscMPIInt size;
8399   Mat        *local;
8400   IS          iscoltmp;
8401   PetscBool   flg;
8402 
8403   PetscFunctionBegin;
8404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8405   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8406   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8407   PetscAssertPointer(newmat, 5);
8408   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8409   PetscValidType(mat, 1);
8410   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8411   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8412 
8413   MatCheckPreallocated(mat, 1);
8414   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8415 
8416   if (!iscol || isrow == iscol) {
8417     PetscBool   stride;
8418     PetscMPIInt grabentirematrix = 0, grab;
8419     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8420     if (stride) {
8421       PetscInt first, step, n, rstart, rend;
8422       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8423       if (step == 1) {
8424         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8425         if (rstart == first) {
8426           PetscCall(ISGetLocalSize(isrow, &n));
8427           if (n == rend - rstart) grabentirematrix = 1;
8428         }
8429       }
8430     }
8431     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8432     if (grab) {
8433       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8434       if (cll == MAT_INITIAL_MATRIX) {
8435         *newmat = mat;
8436         PetscCall(PetscObjectReference((PetscObject)mat));
8437       }
8438       PetscFunctionReturn(PETSC_SUCCESS);
8439     }
8440   }
8441 
8442   if (!iscol) {
8443     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8444   } else {
8445     iscoltmp = iscol;
8446   }
8447 
8448   /* if original matrix is on just one processor then use submatrix generated */
8449   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8450     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8451     goto setproperties;
8452   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8453     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8454     *newmat = *local;
8455     PetscCall(PetscFree(local));
8456     goto setproperties;
8457   } else if (!mat->ops->createsubmatrix) {
8458     /* Create a new matrix type that implements the operation using the full matrix */
8459     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8460     switch (cll) {
8461     case MAT_INITIAL_MATRIX:
8462       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8463       break;
8464     case MAT_REUSE_MATRIX:
8465       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8466       break;
8467     default:
8468       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8469     }
8470     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8471     goto setproperties;
8472   }
8473 
8474   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8475   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8476   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8477 
8478 setproperties:
8479   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8480   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8481   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8482   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8483   PetscFunctionReturn(PETSC_SUCCESS);
8484 }
8485 
8486 /*@
8487   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8488 
8489   Not Collective
8490 
8491   Input Parameters:
8492 + A - the matrix we wish to propagate options from
8493 - B - the matrix we wish to propagate options to
8494 
8495   Level: beginner
8496 
8497   Note:
8498   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8499 
8500 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8501 @*/
8502 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8503 {
8504   PetscFunctionBegin;
8505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8506   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8507   B->symmetry_eternal            = A->symmetry_eternal;
8508   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8509   B->symmetric                   = A->symmetric;
8510   B->structurally_symmetric      = A->structurally_symmetric;
8511   B->spd                         = A->spd;
8512   B->hermitian                   = A->hermitian;
8513   PetscFunctionReturn(PETSC_SUCCESS);
8514 }
8515 
8516 /*@
8517   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8518   used during the assembly process to store values that belong to
8519   other processors.
8520 
8521   Not Collective
8522 
8523   Input Parameters:
8524 + mat   - the matrix
8525 . size  - the initial size of the stash.
8526 - bsize - the initial size of the block-stash(if used).
8527 
8528   Options Database Keys:
8529 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8530 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8531 
8532   Level: intermediate
8533 
8534   Notes:
8535   The block-stash is used for values set with `MatSetValuesBlocked()` while
8536   the stash is used for values set with `MatSetValues()`
8537 
8538   Run with the option -info and look for output of the form
8539   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8540   to determine the appropriate value, MM, to use for size and
8541   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8542   to determine the value, BMM to use for bsize
8543 
8544 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8545 @*/
8546 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8547 {
8548   PetscFunctionBegin;
8549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8550   PetscValidType(mat, 1);
8551   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8552   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8553   PetscFunctionReturn(PETSC_SUCCESS);
8554 }
8555 
8556 /*@
8557   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8558   the matrix
8559 
8560   Neighbor-wise Collective
8561 
8562   Input Parameters:
8563 + A - the matrix
8564 . x - the vector to be multiplied by the interpolation operator
8565 - y - the vector to be added to the result
8566 
8567   Output Parameter:
8568 . w - the resulting vector
8569 
8570   Level: intermediate
8571 
8572   Notes:
8573   `w` may be the same vector as `y`.
8574 
8575   This allows one to use either the restriction or interpolation (its transpose)
8576   matrix to do the interpolation
8577 
8578 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8579 @*/
8580 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8581 {
8582   PetscInt M, N, Ny;
8583 
8584   PetscFunctionBegin;
8585   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8586   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8587   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8588   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8589   PetscCall(MatGetSize(A, &M, &N));
8590   PetscCall(VecGetSize(y, &Ny));
8591   if (M == Ny) {
8592     PetscCall(MatMultAdd(A, x, y, w));
8593   } else {
8594     PetscCall(MatMultTransposeAdd(A, x, y, w));
8595   }
8596   PetscFunctionReturn(PETSC_SUCCESS);
8597 }
8598 
8599 /*@
8600   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8601   the matrix
8602 
8603   Neighbor-wise Collective
8604 
8605   Input Parameters:
8606 + A - the matrix
8607 - x - the vector to be interpolated
8608 
8609   Output Parameter:
8610 . y - the resulting vector
8611 
8612   Level: intermediate
8613 
8614   Note:
8615   This allows one to use either the restriction or interpolation (its transpose)
8616   matrix to do the interpolation
8617 
8618 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8619 @*/
8620 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8621 {
8622   PetscInt M, N, Ny;
8623 
8624   PetscFunctionBegin;
8625   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8626   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8627   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8628   PetscCall(MatGetSize(A, &M, &N));
8629   PetscCall(VecGetSize(y, &Ny));
8630   if (M == Ny) {
8631     PetscCall(MatMult(A, x, y));
8632   } else {
8633     PetscCall(MatMultTranspose(A, x, y));
8634   }
8635   PetscFunctionReturn(PETSC_SUCCESS);
8636 }
8637 
8638 /*@
8639   MatRestrict - $y = A*x$ or $A^T*x$
8640 
8641   Neighbor-wise Collective
8642 
8643   Input Parameters:
8644 + A - the matrix
8645 - x - the vector to be restricted
8646 
8647   Output Parameter:
8648 . y - the resulting vector
8649 
8650   Level: intermediate
8651 
8652   Note:
8653   This allows one to use either the restriction or interpolation (its transpose)
8654   matrix to do the restriction
8655 
8656 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8657 @*/
8658 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8659 {
8660   PetscInt M, N, Ny;
8661 
8662   PetscFunctionBegin;
8663   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8664   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8665   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8666   PetscCall(MatGetSize(A, &M, &N));
8667   PetscCall(VecGetSize(y, &Ny));
8668   if (M == Ny) {
8669     PetscCall(MatMult(A, x, y));
8670   } else {
8671     PetscCall(MatMultTranspose(A, x, y));
8672   }
8673   PetscFunctionReturn(PETSC_SUCCESS);
8674 }
8675 
8676 /*@
8677   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8678 
8679   Neighbor-wise Collective
8680 
8681   Input Parameters:
8682 + A - the matrix
8683 . x - the input dense matrix to be multiplied
8684 - w - the input dense matrix to be added to the result
8685 
8686   Output Parameter:
8687 . y - the output dense matrix
8688 
8689   Level: intermediate
8690 
8691   Note:
8692   This allows one to use either the restriction or interpolation (its transpose)
8693   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8694   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8695 
8696 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8697 @*/
8698 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8699 {
8700   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8701   PetscBool trans = PETSC_TRUE;
8702   MatReuse  reuse = MAT_INITIAL_MATRIX;
8703 
8704   PetscFunctionBegin;
8705   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8706   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8707   PetscValidType(x, 2);
8708   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8709   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8710   PetscCall(MatGetSize(A, &M, &N));
8711   PetscCall(MatGetSize(x, &Mx, &Nx));
8712   if (N == Mx) trans = PETSC_FALSE;
8713   else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx);
8714   Mo = trans ? N : M;
8715   if (*y) {
8716     PetscCall(MatGetSize(*y, &My, &Ny));
8717     if (Mo == My && Nx == Ny) {
8718       reuse = MAT_REUSE_MATRIX;
8719     } else {
8720       PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny);
8721       PetscCall(MatDestroy(y));
8722     }
8723   }
8724 
8725   if (w && *y == w) { /* this is to minimize changes in PCMG */
8726     PetscBool flg;
8727 
8728     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8729     if (w) {
8730       PetscInt My, Ny, Mw, Nw;
8731 
8732       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8733       PetscCall(MatGetSize(*y, &My, &Ny));
8734       PetscCall(MatGetSize(w, &Mw, &Nw));
8735       if (!flg || My != Mw || Ny != Nw) w = NULL;
8736     }
8737     if (!w) {
8738       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8739       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8740       PetscCall(PetscObjectDereference((PetscObject)w));
8741     } else {
8742       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8743     }
8744   }
8745   if (!trans) {
8746     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8747   } else {
8748     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8749   }
8750   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8751   PetscFunctionReturn(PETSC_SUCCESS);
8752 }
8753 
8754 /*@
8755   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8756 
8757   Neighbor-wise Collective
8758 
8759   Input Parameters:
8760 + A - the matrix
8761 - x - the input dense matrix
8762 
8763   Output Parameter:
8764 . y - the output dense matrix
8765 
8766   Level: intermediate
8767 
8768   Note:
8769   This allows one to use either the restriction or interpolation (its transpose)
8770   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8771   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8772 
8773 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8774 @*/
8775 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8776 {
8777   PetscFunctionBegin;
8778   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8779   PetscFunctionReturn(PETSC_SUCCESS);
8780 }
8781 
8782 /*@
8783   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8784 
8785   Neighbor-wise Collective
8786 
8787   Input Parameters:
8788 + A - the matrix
8789 - x - the input dense matrix
8790 
8791   Output Parameter:
8792 . y - the output dense matrix
8793 
8794   Level: intermediate
8795 
8796   Note:
8797   This allows one to use either the restriction or interpolation (its transpose)
8798   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8799   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8800 
8801 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8802 @*/
8803 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8804 {
8805   PetscFunctionBegin;
8806   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8807   PetscFunctionReturn(PETSC_SUCCESS);
8808 }
8809 
8810 /*@
8811   MatGetNullSpace - retrieves the null space of a matrix.
8812 
8813   Logically Collective
8814 
8815   Input Parameters:
8816 + mat    - the matrix
8817 - nullsp - the null space object
8818 
8819   Level: developer
8820 
8821 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8822 @*/
8823 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8824 {
8825   PetscFunctionBegin;
8826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8827   PetscAssertPointer(nullsp, 2);
8828   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8829   PetscFunctionReturn(PETSC_SUCCESS);
8830 }
8831 
8832 /*@
8833   MatSetNullSpace - attaches a null space to a matrix.
8834 
8835   Logically Collective
8836 
8837   Input Parameters:
8838 + mat    - the matrix
8839 - nullsp - the null space object
8840 
8841   Level: advanced
8842 
8843   Notes:
8844   This null space is used by the `KSP` linear solvers to solve singular systems.
8845 
8846   Overwrites any previous null space that may have been attached. You can remove the null space from the matrix object by calling this routine with an nullsp of `NULL`
8847 
8848   For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8849   to zero but the linear system will still be solved in a least squares sense.
8850 
8851   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8852   the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$.
8853   Similarly $R^m$ = direct sum n($A^T$) + R(A).  Hence the linear system $A x = b$ has a solution only if b in R(A) (or correspondingly b is orthogonal to
8854   n($A^T$)) and if x is a solution then x + alpha n(A) is a solution for any alpha. The minimum norm solution is orthogonal to n(A). For problems without a solution
8855   the solution that minimizes the norm of the residual (the least squares solution) can be obtained by solving A x = \hat{b} where \hat{b} is b orthogonalized to the n($A^T$).
8856   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8857 
8858   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8859   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8860   routine also automatically calls `MatSetTransposeNullSpace()`.
8861 
8862   The user should call `MatNullSpaceDestroy()`.
8863 
8864 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8865           `KSPSetPCSide()`
8866 @*/
8867 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8868 {
8869   PetscFunctionBegin;
8870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8871   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8872   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8873   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8874   mat->nullsp = nullsp;
8875   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8876   PetscFunctionReturn(PETSC_SUCCESS);
8877 }
8878 
8879 /*@
8880   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8881 
8882   Logically Collective
8883 
8884   Input Parameters:
8885 + mat    - the matrix
8886 - nullsp - the null space object
8887 
8888   Level: developer
8889 
8890 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8891 @*/
8892 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8893 {
8894   PetscFunctionBegin;
8895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8896   PetscValidType(mat, 1);
8897   PetscAssertPointer(nullsp, 2);
8898   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8899   PetscFunctionReturn(PETSC_SUCCESS);
8900 }
8901 
8902 /*@
8903   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8904 
8905   Logically Collective
8906 
8907   Input Parameters:
8908 + mat    - the matrix
8909 - nullsp - the null space object
8910 
8911   Level: advanced
8912 
8913   Notes:
8914   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8915 
8916   See `MatSetNullSpace()`
8917 
8918 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8919 @*/
8920 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8921 {
8922   PetscFunctionBegin;
8923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8924   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8925   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8926   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8927   mat->transnullsp = nullsp;
8928   PetscFunctionReturn(PETSC_SUCCESS);
8929 }
8930 
8931 /*@
8932   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8933   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8934 
8935   Logically Collective
8936 
8937   Input Parameters:
8938 + mat    - the matrix
8939 - nullsp - the null space object
8940 
8941   Level: advanced
8942 
8943   Notes:
8944   Overwrites any previous near null space that may have been attached
8945 
8946   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8947 
8948 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8949 @*/
8950 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8951 {
8952   PetscFunctionBegin;
8953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8954   PetscValidType(mat, 1);
8955   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8956   MatCheckPreallocated(mat, 1);
8957   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8958   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8959   mat->nearnullsp = nullsp;
8960   PetscFunctionReturn(PETSC_SUCCESS);
8961 }
8962 
8963 /*@
8964   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8965 
8966   Not Collective
8967 
8968   Input Parameter:
8969 . mat - the matrix
8970 
8971   Output Parameter:
8972 . nullsp - the null space object, `NULL` if not set
8973 
8974   Level: advanced
8975 
8976 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8977 @*/
8978 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8979 {
8980   PetscFunctionBegin;
8981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8982   PetscValidType(mat, 1);
8983   PetscAssertPointer(nullsp, 2);
8984   MatCheckPreallocated(mat, 1);
8985   *nullsp = mat->nearnullsp;
8986   PetscFunctionReturn(PETSC_SUCCESS);
8987 }
8988 
8989 /*@C
8990   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8991 
8992   Collective
8993 
8994   Input Parameters:
8995 + mat  - the matrix
8996 . row  - row/column permutation
8997 - info - information on desired factorization process
8998 
8999   Level: developer
9000 
9001   Notes:
9002   Probably really in-place only when level of fill is zero, otherwise allocates
9003   new space to store factored matrix and deletes previous memory.
9004 
9005   Most users should employ the `KSP` interface for linear solvers
9006   instead of working directly with matrix algebra routines such as this.
9007   See, e.g., `KSPCreate()`.
9008 
9009   Developer Note:
9010   The Fortran interface is not autogenerated as the
9011   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9012 
9013 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9014 @*/
9015 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9016 {
9017   PetscFunctionBegin;
9018   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9019   PetscValidType(mat, 1);
9020   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9021   PetscAssertPointer(info, 3);
9022   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9023   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9024   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9025   MatCheckPreallocated(mat, 1);
9026   PetscUseTypeMethod(mat, iccfactor, row, info);
9027   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9028   PetscFunctionReturn(PETSC_SUCCESS);
9029 }
9030 
9031 /*@
9032   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9033   ghosted ones.
9034 
9035   Not Collective
9036 
9037   Input Parameters:
9038 + mat  - the matrix
9039 - diag - the diagonal values, including ghost ones
9040 
9041   Level: developer
9042 
9043   Notes:
9044   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9045 
9046   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9047 
9048 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9049 @*/
9050 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9051 {
9052   PetscMPIInt size;
9053 
9054   PetscFunctionBegin;
9055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9056   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9057   PetscValidType(mat, 1);
9058 
9059   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9060   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9061   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9062   if (size == 1) {
9063     PetscInt n, m;
9064     PetscCall(VecGetSize(diag, &n));
9065     PetscCall(MatGetSize(mat, NULL, &m));
9066     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9067     PetscCall(MatDiagonalScale(mat, NULL, diag));
9068   } else {
9069     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9070   }
9071   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9072   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9073   PetscFunctionReturn(PETSC_SUCCESS);
9074 }
9075 
9076 /*@
9077   MatGetInertia - Gets the inertia from a factored matrix
9078 
9079   Collective
9080 
9081   Input Parameter:
9082 . mat - the matrix
9083 
9084   Output Parameters:
9085 + nneg  - number of negative eigenvalues
9086 . nzero - number of zero eigenvalues
9087 - npos  - number of positive eigenvalues
9088 
9089   Level: advanced
9090 
9091   Note:
9092   Matrix must have been factored by `MatCholeskyFactor()`
9093 
9094 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9095 @*/
9096 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9097 {
9098   PetscFunctionBegin;
9099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9100   PetscValidType(mat, 1);
9101   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9103   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9104   PetscFunctionReturn(PETSC_SUCCESS);
9105 }
9106 
9107 /*@C
9108   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9109 
9110   Neighbor-wise Collective
9111 
9112   Input Parameters:
9113 + mat - the factored matrix obtained with `MatGetFactor()`
9114 - b   - the right-hand-side vectors
9115 
9116   Output Parameter:
9117 . x - the result vectors
9118 
9119   Level: developer
9120 
9121   Note:
9122   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9123   call `MatSolves`(A,x,x).
9124 
9125 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9126 @*/
9127 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9128 {
9129   PetscFunctionBegin;
9130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9131   PetscValidType(mat, 1);
9132   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9133   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9134   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9135 
9136   MatCheckPreallocated(mat, 1);
9137   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9138   PetscUseTypeMethod(mat, solves, b, x);
9139   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9140   PetscFunctionReturn(PETSC_SUCCESS);
9141 }
9142 
9143 /*@
9144   MatIsSymmetric - Test whether a matrix is symmetric
9145 
9146   Collective
9147 
9148   Input Parameters:
9149 + A   - the matrix to test
9150 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9151 
9152   Output Parameter:
9153 . flg - the result
9154 
9155   Level: intermediate
9156 
9157   Notes:
9158   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9159 
9160   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9161 
9162   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9163   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9164 
9165 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9166           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9167 @*/
9168 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9169 {
9170   PetscFunctionBegin;
9171   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9172   PetscAssertPointer(flg, 3);
9173 
9174   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9175   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9176   else {
9177     PetscUseTypeMethod(A, issymmetric, tol, flg);
9178     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9179   }
9180   PetscFunctionReturn(PETSC_SUCCESS);
9181 }
9182 
9183 /*@
9184   MatIsHermitian - Test whether a matrix is Hermitian
9185 
9186   Collective
9187 
9188   Input Parameters:
9189 + A   - the matrix to test
9190 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9191 
9192   Output Parameter:
9193 . flg - the result
9194 
9195   Level: intermediate
9196 
9197   Notes:
9198   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9199 
9200   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9201 
9202   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9203   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9204 
9205 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9206           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9207 @*/
9208 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9209 {
9210   PetscFunctionBegin;
9211   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9212   PetscAssertPointer(flg, 3);
9213 
9214   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9215   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9216   else {
9217     PetscUseTypeMethod(A, ishermitian, tol, flg);
9218     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9219   }
9220   PetscFunctionReturn(PETSC_SUCCESS);
9221 }
9222 
9223 /*@
9224   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9225 
9226   Not Collective
9227 
9228   Input Parameter:
9229 . A - the matrix to check
9230 
9231   Output Parameters:
9232 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9233 - flg - the result (only valid if set is `PETSC_TRUE`)
9234 
9235   Level: advanced
9236 
9237   Notes:
9238   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9239   if you want it explicitly checked
9240 
9241   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9242   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9243 
9244 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9245 @*/
9246 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9247 {
9248   PetscFunctionBegin;
9249   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9250   PetscAssertPointer(set, 2);
9251   PetscAssertPointer(flg, 3);
9252   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9253     *set = PETSC_TRUE;
9254     *flg = PetscBool3ToBool(A->symmetric);
9255   } else {
9256     *set = PETSC_FALSE;
9257   }
9258   PetscFunctionReturn(PETSC_SUCCESS);
9259 }
9260 
9261 /*@
9262   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9263 
9264   Not Collective
9265 
9266   Input Parameter:
9267 . A - the matrix to check
9268 
9269   Output Parameters:
9270 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9271 - flg - the result (only valid if set is `PETSC_TRUE`)
9272 
9273   Level: advanced
9274 
9275   Notes:
9276   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9277 
9278   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9279   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9280 
9281 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9282 @*/
9283 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9284 {
9285   PetscFunctionBegin;
9286   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9287   PetscAssertPointer(set, 2);
9288   PetscAssertPointer(flg, 3);
9289   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9290     *set = PETSC_TRUE;
9291     *flg = PetscBool3ToBool(A->spd);
9292   } else {
9293     *set = PETSC_FALSE;
9294   }
9295   PetscFunctionReturn(PETSC_SUCCESS);
9296 }
9297 
9298 /*@
9299   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9300 
9301   Not Collective
9302 
9303   Input Parameter:
9304 . A - the matrix to check
9305 
9306   Output Parameters:
9307 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9308 - flg - the result (only valid if set is `PETSC_TRUE`)
9309 
9310   Level: advanced
9311 
9312   Notes:
9313   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9314   if you want it explicitly checked
9315 
9316   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9317   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9318 
9319 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9320 @*/
9321 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9322 {
9323   PetscFunctionBegin;
9324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9325   PetscAssertPointer(set, 2);
9326   PetscAssertPointer(flg, 3);
9327   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9328     *set = PETSC_TRUE;
9329     *flg = PetscBool3ToBool(A->hermitian);
9330   } else {
9331     *set = PETSC_FALSE;
9332   }
9333   PetscFunctionReturn(PETSC_SUCCESS);
9334 }
9335 
9336 /*@
9337   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9338 
9339   Collective
9340 
9341   Input Parameter:
9342 . A - the matrix to test
9343 
9344   Output Parameter:
9345 . flg - the result
9346 
9347   Level: intermediate
9348 
9349   Notes:
9350   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9351 
9352   One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9353   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9354 
9355 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9356 @*/
9357 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9358 {
9359   PetscFunctionBegin;
9360   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9361   PetscAssertPointer(flg, 2);
9362   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9363     *flg = PetscBool3ToBool(A->structurally_symmetric);
9364   } else {
9365     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9366     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9367   }
9368   PetscFunctionReturn(PETSC_SUCCESS);
9369 }
9370 
9371 /*@
9372   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9373 
9374   Not Collective
9375 
9376   Input Parameter:
9377 . A - the matrix to check
9378 
9379   Output Parameters:
9380 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9381 - flg - the result (only valid if set is PETSC_TRUE)
9382 
9383   Level: advanced
9384 
9385   Notes:
9386   One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally
9387   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9388 
9389   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9390 
9391 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9392 @*/
9393 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9394 {
9395   PetscFunctionBegin;
9396   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9397   PetscAssertPointer(set, 2);
9398   PetscAssertPointer(flg, 3);
9399   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9400     *set = PETSC_TRUE;
9401     *flg = PetscBool3ToBool(A->structurally_symmetric);
9402   } else {
9403     *set = PETSC_FALSE;
9404   }
9405   PetscFunctionReturn(PETSC_SUCCESS);
9406 }
9407 
9408 /*@
9409   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9410   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9411 
9412   Not Collective
9413 
9414   Input Parameter:
9415 . mat - the matrix
9416 
9417   Output Parameters:
9418 + nstash    - the size of the stash
9419 . reallocs  - the number of additional mallocs incurred.
9420 . bnstash   - the size of the block stash
9421 - breallocs - the number of additional mallocs incurred.in the block stash
9422 
9423   Level: advanced
9424 
9425 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9426 @*/
9427 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9428 {
9429   PetscFunctionBegin;
9430   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9431   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9432   PetscFunctionReturn(PETSC_SUCCESS);
9433 }
9434 
9435 /*@C
9436   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9437   parallel layout, `PetscLayout` for rows and columns
9438 
9439   Collective
9440 
9441   Input Parameter:
9442 . mat - the matrix
9443 
9444   Output Parameters:
9445 + right - (optional) vector that the matrix can be multiplied against
9446 - left  - (optional) vector that the matrix vector product can be stored in
9447 
9448   Level: advanced
9449 
9450   Notes:
9451   The blocksize of the returned vectors is determined by the row and column block sizes set with `MatSetBlockSizes()` or the single blocksize (same for both) set by `MatSetBlockSize()`.
9452 
9453   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9454 
9455 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9456 @*/
9457 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9458 {
9459   PetscFunctionBegin;
9460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9461   PetscValidType(mat, 1);
9462   if (mat->ops->getvecs) {
9463     PetscUseTypeMethod(mat, getvecs, right, left);
9464   } else {
9465     if (right) {
9466       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9467       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9468       PetscCall(VecSetType(*right, mat->defaultvectype));
9469 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9470       if (mat->boundtocpu && mat->bindingpropagates) {
9471         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9472         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9473       }
9474 #endif
9475     }
9476     if (left) {
9477       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9478       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9479       PetscCall(VecSetType(*left, mat->defaultvectype));
9480 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9481       if (mat->boundtocpu && mat->bindingpropagates) {
9482         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9483         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9484       }
9485 #endif
9486     }
9487   }
9488   PetscFunctionReturn(PETSC_SUCCESS);
9489 }
9490 
9491 /*@C
9492   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9493   with default values.
9494 
9495   Not Collective
9496 
9497   Input Parameter:
9498 . info - the `MatFactorInfo` data structure
9499 
9500   Level: developer
9501 
9502   Notes:
9503   The solvers are generally used through the `KSP` and `PC` objects, for example
9504   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9505 
9506   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9507 
9508   Developer Note:
9509   The Fortran interface is not autogenerated as the
9510   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9511 
9512 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9513 @*/
9514 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9515 {
9516   PetscFunctionBegin;
9517   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9518   PetscFunctionReturn(PETSC_SUCCESS);
9519 }
9520 
9521 /*@
9522   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9523 
9524   Collective
9525 
9526   Input Parameters:
9527 + mat - the factored matrix
9528 - is  - the index set defining the Schur indices (0-based)
9529 
9530   Level: advanced
9531 
9532   Notes:
9533   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9534 
9535   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9536 
9537   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9538 
9539 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9540           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9541 @*/
9542 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9543 {
9544   PetscErrorCode (*f)(Mat, IS);
9545 
9546   PetscFunctionBegin;
9547   PetscValidType(mat, 1);
9548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9549   PetscValidType(is, 2);
9550   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9551   PetscCheckSameComm(mat, 1, is, 2);
9552   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9553   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9554   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9555   PetscCall(MatDestroy(&mat->schur));
9556   PetscCall((*f)(mat, is));
9557   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9558   PetscFunctionReturn(PETSC_SUCCESS);
9559 }
9560 
9561 /*@
9562   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9563 
9564   Logically Collective
9565 
9566   Input Parameters:
9567 + F      - the factored matrix obtained by calling `MatGetFactor()`
9568 . S      - location where to return the Schur complement, can be `NULL`
9569 - status - the status of the Schur complement matrix, can be `NULL`
9570 
9571   Level: advanced
9572 
9573   Notes:
9574   You must call `MatFactorSetSchurIS()` before calling this routine.
9575 
9576   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9577 
9578   The routine provides a copy of the Schur matrix stored within the solver data structures.
9579   The caller must destroy the object when it is no longer needed.
9580   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9581 
9582   Use `MatFactorGetSchurComplement()` to get access to the Schur complement matrix inside the factored matrix instead of making a copy of it (which this function does)
9583 
9584   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9585 
9586   Developer Note:
9587   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9588   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9589 
9590 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9591 @*/
9592 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9593 {
9594   PetscFunctionBegin;
9595   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9596   if (S) PetscAssertPointer(S, 2);
9597   if (status) PetscAssertPointer(status, 3);
9598   if (S) {
9599     PetscErrorCode (*f)(Mat, Mat *);
9600 
9601     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9602     if (f) {
9603       PetscCall((*f)(F, S));
9604     } else {
9605       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9606     }
9607   }
9608   if (status) *status = F->schur_status;
9609   PetscFunctionReturn(PETSC_SUCCESS);
9610 }
9611 
9612 /*@
9613   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9614 
9615   Logically Collective
9616 
9617   Input Parameters:
9618 + F      - the factored matrix obtained by calling `MatGetFactor()`
9619 . S      - location where to return the Schur complement, can be `NULL`
9620 - status - the status of the Schur complement matrix, can be `NULL`
9621 
9622   Level: advanced
9623 
9624   Notes:
9625   You must call `MatFactorSetSchurIS()` before calling this routine.
9626 
9627   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9628 
9629   The routine returns a the Schur Complement stored within the data structures of the solver.
9630 
9631   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9632 
9633   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9634 
9635   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9636 
9637   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9638 
9639 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9640 @*/
9641 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9642 {
9643   PetscFunctionBegin;
9644   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9645   if (S) {
9646     PetscAssertPointer(S, 2);
9647     *S = F->schur;
9648   }
9649   if (status) {
9650     PetscAssertPointer(status, 3);
9651     *status = F->schur_status;
9652   }
9653   PetscFunctionReturn(PETSC_SUCCESS);
9654 }
9655 
9656 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9657 {
9658   Mat S = F->schur;
9659 
9660   PetscFunctionBegin;
9661   switch (F->schur_status) {
9662   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9663   case MAT_FACTOR_SCHUR_INVERTED:
9664     if (S) {
9665       S->ops->solve             = NULL;
9666       S->ops->matsolve          = NULL;
9667       S->ops->solvetranspose    = NULL;
9668       S->ops->matsolvetranspose = NULL;
9669       S->ops->solveadd          = NULL;
9670       S->ops->solvetransposeadd = NULL;
9671       S->factortype             = MAT_FACTOR_NONE;
9672       PetscCall(PetscFree(S->solvertype));
9673     }
9674   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9675     break;
9676   default:
9677     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9678   }
9679   PetscFunctionReturn(PETSC_SUCCESS);
9680 }
9681 
9682 /*@
9683   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9684 
9685   Logically Collective
9686 
9687   Input Parameters:
9688 + F      - the factored matrix obtained by calling `MatGetFactor()`
9689 . S      - location where the Schur complement is stored
9690 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9691 
9692   Level: advanced
9693 
9694 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9695 @*/
9696 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9697 {
9698   PetscFunctionBegin;
9699   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9700   if (S) {
9701     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9702     *S = NULL;
9703   }
9704   F->schur_status = status;
9705   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9706   PetscFunctionReturn(PETSC_SUCCESS);
9707 }
9708 
9709 /*@
9710   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9711 
9712   Logically Collective
9713 
9714   Input Parameters:
9715 + F   - the factored matrix obtained by calling `MatGetFactor()`
9716 . rhs - location where the right hand side of the Schur complement system is stored
9717 - sol - location where the solution of the Schur complement system has to be returned
9718 
9719   Level: advanced
9720 
9721   Notes:
9722   The sizes of the vectors should match the size of the Schur complement
9723 
9724   Must be called after `MatFactorSetSchurIS()`
9725 
9726 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9727 @*/
9728 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9729 {
9730   PetscFunctionBegin;
9731   PetscValidType(F, 1);
9732   PetscValidType(rhs, 2);
9733   PetscValidType(sol, 3);
9734   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9735   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9736   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9737   PetscCheckSameComm(F, 1, rhs, 2);
9738   PetscCheckSameComm(F, 1, sol, 3);
9739   PetscCall(MatFactorFactorizeSchurComplement(F));
9740   switch (F->schur_status) {
9741   case MAT_FACTOR_SCHUR_FACTORED:
9742     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9743     break;
9744   case MAT_FACTOR_SCHUR_INVERTED:
9745     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9746     break;
9747   default:
9748     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9749   }
9750   PetscFunctionReturn(PETSC_SUCCESS);
9751 }
9752 
9753 /*@
9754   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9755 
9756   Logically Collective
9757 
9758   Input Parameters:
9759 + F   - the factored matrix obtained by calling `MatGetFactor()`
9760 . rhs - location where the right hand side of the Schur complement system is stored
9761 - sol - location where the solution of the Schur complement system has to be returned
9762 
9763   Level: advanced
9764 
9765   Notes:
9766   The sizes of the vectors should match the size of the Schur complement
9767 
9768   Must be called after `MatFactorSetSchurIS()`
9769 
9770 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9771 @*/
9772 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9773 {
9774   PetscFunctionBegin;
9775   PetscValidType(F, 1);
9776   PetscValidType(rhs, 2);
9777   PetscValidType(sol, 3);
9778   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9779   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9780   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9781   PetscCheckSameComm(F, 1, rhs, 2);
9782   PetscCheckSameComm(F, 1, sol, 3);
9783   PetscCall(MatFactorFactorizeSchurComplement(F));
9784   switch (F->schur_status) {
9785   case MAT_FACTOR_SCHUR_FACTORED:
9786     PetscCall(MatSolve(F->schur, rhs, sol));
9787     break;
9788   case MAT_FACTOR_SCHUR_INVERTED:
9789     PetscCall(MatMult(F->schur, rhs, sol));
9790     break;
9791   default:
9792     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9793   }
9794   PetscFunctionReturn(PETSC_SUCCESS);
9795 }
9796 
9797 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9798 #if PetscDefined(HAVE_CUDA)
9799 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9800 #endif
9801 
9802 /* Schur status updated in the interface */
9803 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9804 {
9805   Mat S = F->schur;
9806 
9807   PetscFunctionBegin;
9808   if (S) {
9809     PetscMPIInt size;
9810     PetscBool   isdense, isdensecuda;
9811 
9812     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9813     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9814     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9815     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9816     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9817     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9818     if (isdense) {
9819       PetscCall(MatSeqDenseInvertFactors_Private(S));
9820     } else if (isdensecuda) {
9821 #if defined(PETSC_HAVE_CUDA)
9822       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9823 #endif
9824     }
9825     // HIP??????????????
9826     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9827   }
9828   PetscFunctionReturn(PETSC_SUCCESS);
9829 }
9830 
9831 /*@
9832   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9833 
9834   Logically Collective
9835 
9836   Input Parameter:
9837 . F - the factored matrix obtained by calling `MatGetFactor()`
9838 
9839   Level: advanced
9840 
9841   Notes:
9842   Must be called after `MatFactorSetSchurIS()`.
9843 
9844   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9845 
9846 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9847 @*/
9848 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9849 {
9850   PetscFunctionBegin;
9851   PetscValidType(F, 1);
9852   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9853   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9854   PetscCall(MatFactorFactorizeSchurComplement(F));
9855   PetscCall(MatFactorInvertSchurComplement_Private(F));
9856   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9857   PetscFunctionReturn(PETSC_SUCCESS);
9858 }
9859 
9860 /*@
9861   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9862 
9863   Logically Collective
9864 
9865   Input Parameter:
9866 . F - the factored matrix obtained by calling `MatGetFactor()`
9867 
9868   Level: advanced
9869 
9870   Note:
9871   Must be called after `MatFactorSetSchurIS()`
9872 
9873 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9874 @*/
9875 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9876 {
9877   MatFactorInfo info;
9878 
9879   PetscFunctionBegin;
9880   PetscValidType(F, 1);
9881   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9882   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9883   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9884   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9885   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9886     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9887   } else {
9888     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9889   }
9890   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9891   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9892   PetscFunctionReturn(PETSC_SUCCESS);
9893 }
9894 
9895 /*@
9896   MatPtAP - Creates the matrix product $C = P^T * A * P$
9897 
9898   Neighbor-wise Collective
9899 
9900   Input Parameters:
9901 + A     - the matrix
9902 . P     - the projection matrix
9903 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9904 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9905           if the result is a dense matrix this is irrelevant
9906 
9907   Output Parameter:
9908 . C - the product matrix
9909 
9910   Level: intermediate
9911 
9912   Notes:
9913   C will be created and must be destroyed by the user with `MatDestroy()`.
9914 
9915   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9916 
9917   Developer Note:
9918   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9919 
9920 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9921 @*/
9922 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9923 {
9924   PetscFunctionBegin;
9925   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9926   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9927 
9928   if (scall == MAT_INITIAL_MATRIX) {
9929     PetscCall(MatProductCreate(A, P, NULL, C));
9930     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9931     PetscCall(MatProductSetAlgorithm(*C, "default"));
9932     PetscCall(MatProductSetFill(*C, fill));
9933 
9934     (*C)->product->api_user = PETSC_TRUE;
9935     PetscCall(MatProductSetFromOptions(*C));
9936     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);
9937     PetscCall(MatProductSymbolic(*C));
9938   } else { /* scall == MAT_REUSE_MATRIX */
9939     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9940   }
9941 
9942   PetscCall(MatProductNumeric(*C));
9943   (*C)->symmetric = A->symmetric;
9944   (*C)->spd       = A->spd;
9945   PetscFunctionReturn(PETSC_SUCCESS);
9946 }
9947 
9948 /*@
9949   MatRARt - Creates the matrix product $C = R * A * R^T$
9950 
9951   Neighbor-wise Collective
9952 
9953   Input Parameters:
9954 + A     - the matrix
9955 . R     - the projection matrix
9956 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9957 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9958           if the result is a dense matrix this is irrelevant
9959 
9960   Output Parameter:
9961 . C - the product matrix
9962 
9963   Level: intermediate
9964 
9965   Notes:
9966   C will be created and must be destroyed by the user with `MatDestroy()`.
9967 
9968   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9969 
9970   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9971   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9972   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9973   We recommend using MatPtAP().
9974 
9975 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9976 @*/
9977 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9978 {
9979   PetscFunctionBegin;
9980   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9981   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9982 
9983   if (scall == MAT_INITIAL_MATRIX) {
9984     PetscCall(MatProductCreate(A, R, NULL, C));
9985     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9986     PetscCall(MatProductSetAlgorithm(*C, "default"));
9987     PetscCall(MatProductSetFill(*C, fill));
9988 
9989     (*C)->product->api_user = PETSC_TRUE;
9990     PetscCall(MatProductSetFromOptions(*C));
9991     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);
9992     PetscCall(MatProductSymbolic(*C));
9993   } else { /* scall == MAT_REUSE_MATRIX */
9994     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9995   }
9996 
9997   PetscCall(MatProductNumeric(*C));
9998   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9999   PetscFunctionReturn(PETSC_SUCCESS);
10000 }
10001 
10002 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10003 {
10004   PetscFunctionBegin;
10005   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10006 
10007   if (scall == MAT_INITIAL_MATRIX) {
10008     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10009     PetscCall(MatProductCreate(A, B, NULL, C));
10010     PetscCall(MatProductSetType(*C, ptype));
10011     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10012     PetscCall(MatProductSetFill(*C, fill));
10013 
10014     (*C)->product->api_user = PETSC_TRUE;
10015     PetscCall(MatProductSetFromOptions(*C));
10016     PetscCall(MatProductSymbolic(*C));
10017   } else { /* scall == MAT_REUSE_MATRIX */
10018     Mat_Product *product = (*C)->product;
10019     PetscBool    isdense;
10020 
10021     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10022     if (isdense && product && product->type != ptype) {
10023       PetscCall(MatProductClear(*C));
10024       product = NULL;
10025     }
10026     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10027     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10028       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10029       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10030       product           = (*C)->product;
10031       product->fill     = fill;
10032       product->api_user = PETSC_TRUE;
10033       product->clear    = PETSC_TRUE;
10034 
10035       PetscCall(MatProductSetType(*C, ptype));
10036       PetscCall(MatProductSetFromOptions(*C));
10037       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);
10038       PetscCall(MatProductSymbolic(*C));
10039     } else { /* user may change input matrices A or B when REUSE */
10040       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10041     }
10042   }
10043   PetscCall(MatProductNumeric(*C));
10044   PetscFunctionReturn(PETSC_SUCCESS);
10045 }
10046 
10047 /*@
10048   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10049 
10050   Neighbor-wise Collective
10051 
10052   Input Parameters:
10053 + A     - the left matrix
10054 . B     - the right matrix
10055 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10056 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10057           if the result is a dense matrix this is irrelevant
10058 
10059   Output Parameter:
10060 . C - the product matrix
10061 
10062   Notes:
10063   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10064 
10065   `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
10066   call to this function with `MAT_INITIAL_MATRIX`.
10067 
10068   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10069 
10070   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`,
10071   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10072 
10073   Example of Usage:
10074 .vb
10075      MatProductCreate(A,B,NULL,&C);
10076      MatProductSetType(C,MATPRODUCT_AB);
10077      MatProductSymbolic(C);
10078      MatProductNumeric(C); // compute C=A * B
10079      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10080      MatProductNumeric(C);
10081      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10082      MatProductNumeric(C);
10083 .ve
10084 
10085   Level: intermediate
10086 
10087 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10088 @*/
10089 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10090 {
10091   PetscFunctionBegin;
10092   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10093   PetscFunctionReturn(PETSC_SUCCESS);
10094 }
10095 
10096 /*@
10097   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10098 
10099   Neighbor-wise Collective
10100 
10101   Input Parameters:
10102 + A     - the left matrix
10103 . B     - the right matrix
10104 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10105 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10106 
10107   Output Parameter:
10108 . C - the product matrix
10109 
10110   Options Database Key:
10111 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10112               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10113               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10114 
10115   Level: intermediate
10116 
10117   Notes:
10118   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10119 
10120   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10121 
10122   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10123   actually needed.
10124 
10125   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10126   and for pairs of `MATMPIDENSE` matrices.
10127 
10128   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10129 
10130 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10131 @*/
10132 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10133 {
10134   PetscFunctionBegin;
10135   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10136   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10137   PetscFunctionReturn(PETSC_SUCCESS);
10138 }
10139 
10140 /*@
10141   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10142 
10143   Neighbor-wise Collective
10144 
10145   Input Parameters:
10146 + A     - the left matrix
10147 . B     - the right matrix
10148 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10149 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10150 
10151   Output Parameter:
10152 . C - the product matrix
10153 
10154   Level: intermediate
10155 
10156   Notes:
10157   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10158 
10159   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10160 
10161   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10162 
10163   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10164   actually needed.
10165 
10166   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10167   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10168 
10169 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10170 @*/
10171 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10172 {
10173   PetscFunctionBegin;
10174   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10175   PetscFunctionReturn(PETSC_SUCCESS);
10176 }
10177 
10178 /*@
10179   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10180 
10181   Neighbor-wise Collective
10182 
10183   Input Parameters:
10184 + A     - the left matrix
10185 . B     - the middle matrix
10186 . C     - the right matrix
10187 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10188 - 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
10189           if the result is a dense matrix this is irrelevant
10190 
10191   Output Parameter:
10192 . D - the product matrix
10193 
10194   Level: intermediate
10195 
10196   Notes:
10197   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10198 
10199   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10200 
10201   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10202 
10203   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10204   actually needed.
10205 
10206   If you have many matrices with the same non-zero structure to multiply, you
10207   should use `MAT_REUSE_MATRIX` in all calls but the first
10208 
10209 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10210 @*/
10211 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10212 {
10213   PetscFunctionBegin;
10214   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10215   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10216 
10217   if (scall == MAT_INITIAL_MATRIX) {
10218     PetscCall(MatProductCreate(A, B, C, D));
10219     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10220     PetscCall(MatProductSetAlgorithm(*D, "default"));
10221     PetscCall(MatProductSetFill(*D, fill));
10222 
10223     (*D)->product->api_user = PETSC_TRUE;
10224     PetscCall(MatProductSetFromOptions(*D));
10225     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,
10226                ((PetscObject)C)->type_name);
10227     PetscCall(MatProductSymbolic(*D));
10228   } else { /* user may change input matrices when REUSE */
10229     PetscCall(MatProductReplaceMats(A, B, C, *D));
10230   }
10231   PetscCall(MatProductNumeric(*D));
10232   PetscFunctionReturn(PETSC_SUCCESS);
10233 }
10234 
10235 /*@
10236   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10237 
10238   Collective
10239 
10240   Input Parameters:
10241 + mat      - the matrix
10242 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10243 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10244 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10245 
10246   Output Parameter:
10247 . matredundant - redundant matrix
10248 
10249   Level: advanced
10250 
10251   Notes:
10252   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10253   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10254 
10255   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10256   calling it.
10257 
10258   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10259 
10260 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10261 @*/
10262 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10263 {
10264   MPI_Comm       comm;
10265   PetscMPIInt    size;
10266   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10267   Mat_Redundant *redund     = NULL;
10268   PetscSubcomm   psubcomm   = NULL;
10269   MPI_Comm       subcomm_in = subcomm;
10270   Mat           *matseq;
10271   IS             isrow, iscol;
10272   PetscBool      newsubcomm = PETSC_FALSE;
10273 
10274   PetscFunctionBegin;
10275   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10276   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10277     PetscAssertPointer(*matredundant, 5);
10278     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10279   }
10280 
10281   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10282   if (size == 1 || nsubcomm == 1) {
10283     if (reuse == MAT_INITIAL_MATRIX) {
10284       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10285     } else {
10286       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");
10287       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10288     }
10289     PetscFunctionReturn(PETSC_SUCCESS);
10290   }
10291 
10292   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10293   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10294   MatCheckPreallocated(mat, 1);
10295 
10296   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10297   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10298     /* create psubcomm, then get subcomm */
10299     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10300     PetscCallMPI(MPI_Comm_size(comm, &size));
10301     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10302 
10303     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10304     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10305     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10306     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10307     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10308     newsubcomm = PETSC_TRUE;
10309     PetscCall(PetscSubcommDestroy(&psubcomm));
10310   }
10311 
10312   /* get isrow, iscol and a local sequential matrix matseq[0] */
10313   if (reuse == MAT_INITIAL_MATRIX) {
10314     mloc_sub = PETSC_DECIDE;
10315     nloc_sub = PETSC_DECIDE;
10316     if (bs < 1) {
10317       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10318       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10319     } else {
10320       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10321       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10322     }
10323     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10324     rstart = rend - mloc_sub;
10325     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10326     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10327     PetscCall(ISSetIdentity(iscol));
10328   } else { /* reuse == MAT_REUSE_MATRIX */
10329     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");
10330     /* retrieve subcomm */
10331     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10332     redund = (*matredundant)->redundant;
10333     isrow  = redund->isrow;
10334     iscol  = redund->iscol;
10335     matseq = redund->matseq;
10336   }
10337   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10338 
10339   /* get matredundant over subcomm */
10340   if (reuse == MAT_INITIAL_MATRIX) {
10341     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10342 
10343     /* create a supporting struct and attach it to C for reuse */
10344     PetscCall(PetscNew(&redund));
10345     (*matredundant)->redundant = redund;
10346     redund->isrow              = isrow;
10347     redund->iscol              = iscol;
10348     redund->matseq             = matseq;
10349     if (newsubcomm) {
10350       redund->subcomm = subcomm;
10351     } else {
10352       redund->subcomm = MPI_COMM_NULL;
10353     }
10354   } else {
10355     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10356   }
10357 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10358   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10359     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10360     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10361   }
10362 #endif
10363   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10364   PetscFunctionReturn(PETSC_SUCCESS);
10365 }
10366 
10367 /*@C
10368   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10369   a given `Mat`. Each submatrix can span multiple procs.
10370 
10371   Collective
10372 
10373   Input Parameters:
10374 + mat     - the matrix
10375 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10376 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10377 
10378   Output Parameter:
10379 . subMat - parallel sub-matrices each spanning a given `subcomm`
10380 
10381   Level: advanced
10382 
10383   Notes:
10384   The submatrix partition across processors is dictated by `subComm` a
10385   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10386   is not restricted to be grouped with consecutive original MPI processes.
10387 
10388   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10389   map directly to the layout of the original matrix [wrt the local
10390   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10391   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10392   the `subMat`. However the offDiagMat looses some columns - and this is
10393   reconstructed with `MatSetValues()`
10394 
10395   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10396 
10397 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10398 @*/
10399 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10400 {
10401   PetscMPIInt commsize, subCommSize;
10402 
10403   PetscFunctionBegin;
10404   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10405   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10406   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10407 
10408   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");
10409   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10410   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10411   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10412   PetscFunctionReturn(PETSC_SUCCESS);
10413 }
10414 
10415 /*@
10416   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10417 
10418   Not Collective
10419 
10420   Input Parameters:
10421 + mat   - matrix to extract local submatrix from
10422 . isrow - local row indices for submatrix
10423 - iscol - local column indices for submatrix
10424 
10425   Output Parameter:
10426 . submat - the submatrix
10427 
10428   Level: intermediate
10429 
10430   Notes:
10431   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10432 
10433   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10434   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10435 
10436   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10437   `MatSetValuesBlockedLocal()` will also be implemented.
10438 
10439   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10440   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10441 
10442 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10443 @*/
10444 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10445 {
10446   PetscFunctionBegin;
10447   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10448   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10449   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10450   PetscCheckSameComm(isrow, 2, iscol, 3);
10451   PetscAssertPointer(submat, 4);
10452   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10453 
10454   if (mat->ops->getlocalsubmatrix) {
10455     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10456   } else {
10457     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10458   }
10459   PetscFunctionReturn(PETSC_SUCCESS);
10460 }
10461 
10462 /*@
10463   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10464 
10465   Not Collective
10466 
10467   Input Parameters:
10468 + mat    - matrix to extract local submatrix from
10469 . isrow  - local row indices for submatrix
10470 . iscol  - local column indices for submatrix
10471 - submat - the submatrix
10472 
10473   Level: intermediate
10474 
10475 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10476 @*/
10477 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10478 {
10479   PetscFunctionBegin;
10480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10481   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10482   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10483   PetscCheckSameComm(isrow, 2, iscol, 3);
10484   PetscAssertPointer(submat, 4);
10485   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10486 
10487   if (mat->ops->restorelocalsubmatrix) {
10488     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10489   } else {
10490     PetscCall(MatDestroy(submat));
10491   }
10492   *submat = NULL;
10493   PetscFunctionReturn(PETSC_SUCCESS);
10494 }
10495 
10496 /*@
10497   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10498 
10499   Collective
10500 
10501   Input Parameter:
10502 . mat - the matrix
10503 
10504   Output Parameter:
10505 . is - if any rows have zero diagonals this contains the list of them
10506 
10507   Level: developer
10508 
10509 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10510 @*/
10511 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10512 {
10513   PetscFunctionBegin;
10514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10515   PetscValidType(mat, 1);
10516   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10517   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10518 
10519   if (!mat->ops->findzerodiagonals) {
10520     Vec                diag;
10521     const PetscScalar *a;
10522     PetscInt          *rows;
10523     PetscInt           rStart, rEnd, r, nrow = 0;
10524 
10525     PetscCall(MatCreateVecs(mat, &diag, NULL));
10526     PetscCall(MatGetDiagonal(mat, diag));
10527     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10528     PetscCall(VecGetArrayRead(diag, &a));
10529     for (r = 0; r < rEnd - rStart; ++r)
10530       if (a[r] == 0.0) ++nrow;
10531     PetscCall(PetscMalloc1(nrow, &rows));
10532     nrow = 0;
10533     for (r = 0; r < rEnd - rStart; ++r)
10534       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10535     PetscCall(VecRestoreArrayRead(diag, &a));
10536     PetscCall(VecDestroy(&diag));
10537     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10538   } else {
10539     PetscUseTypeMethod(mat, findzerodiagonals, is);
10540   }
10541   PetscFunctionReturn(PETSC_SUCCESS);
10542 }
10543 
10544 /*@
10545   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10546 
10547   Collective
10548 
10549   Input Parameter:
10550 . mat - the matrix
10551 
10552   Output Parameter:
10553 . is - contains the list of rows with off block diagonal entries
10554 
10555   Level: developer
10556 
10557 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10558 @*/
10559 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10560 {
10561   PetscFunctionBegin;
10562   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10563   PetscValidType(mat, 1);
10564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10566 
10567   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10568   PetscFunctionReturn(PETSC_SUCCESS);
10569 }
10570 
10571 /*@C
10572   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10573 
10574   Collective; No Fortran Support
10575 
10576   Input Parameter:
10577 . mat - the matrix
10578 
10579   Output Parameter:
10580 . values - the block inverses in column major order (FORTRAN-like)
10581 
10582   Level: advanced
10583 
10584   Notes:
10585   The size of the blocks is determined by the block size of the matrix.
10586 
10587   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10588 
10589   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10590 
10591 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10592 @*/
10593 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10594 {
10595   PetscFunctionBegin;
10596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10597   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10598   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10599   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10600   PetscFunctionReturn(PETSC_SUCCESS);
10601 }
10602 
10603 /*@C
10604   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10605 
10606   Collective; No Fortran Support
10607 
10608   Input Parameters:
10609 + mat     - the matrix
10610 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10611 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10612 
10613   Output Parameter:
10614 . values - the block inverses in column major order (FORTRAN-like)
10615 
10616   Level: advanced
10617 
10618   Notes:
10619   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10620 
10621   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10622 
10623 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10624 @*/
10625 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10626 {
10627   PetscFunctionBegin;
10628   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10629   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10630   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10631   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10632   PetscFunctionReturn(PETSC_SUCCESS);
10633 }
10634 
10635 /*@
10636   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10637 
10638   Collective
10639 
10640   Input Parameters:
10641 + A - the matrix
10642 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10643 
10644   Level: advanced
10645 
10646   Note:
10647   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10648 
10649 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10650 @*/
10651 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10652 {
10653   const PetscScalar *vals;
10654   PetscInt          *dnnz;
10655   PetscInt           m, rstart, rend, bs, i, j;
10656 
10657   PetscFunctionBegin;
10658   PetscCall(MatInvertBlockDiagonal(A, &vals));
10659   PetscCall(MatGetBlockSize(A, &bs));
10660   PetscCall(MatGetLocalSize(A, &m, NULL));
10661   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10662   PetscCall(PetscMalloc1(m / bs, &dnnz));
10663   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10664   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10665   PetscCall(PetscFree(dnnz));
10666   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10667   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10668   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10669   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10670   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10671   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10672   PetscFunctionReturn(PETSC_SUCCESS);
10673 }
10674 
10675 /*@C
10676   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10677   via `MatTransposeColoringCreate()`.
10678 
10679   Collective
10680 
10681   Input Parameter:
10682 . c - coloring context
10683 
10684   Level: intermediate
10685 
10686 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10687 @*/
10688 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10689 {
10690   MatTransposeColoring matcolor = *c;
10691 
10692   PetscFunctionBegin;
10693   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10694   if (--((PetscObject)matcolor)->refct > 0) {
10695     matcolor = NULL;
10696     PetscFunctionReturn(PETSC_SUCCESS);
10697   }
10698 
10699   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10700   PetscCall(PetscFree(matcolor->rows));
10701   PetscCall(PetscFree(matcolor->den2sp));
10702   PetscCall(PetscFree(matcolor->colorforcol));
10703   PetscCall(PetscFree(matcolor->columns));
10704   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10705   PetscCall(PetscHeaderDestroy(c));
10706   PetscFunctionReturn(PETSC_SUCCESS);
10707 }
10708 
10709 /*@C
10710   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10711   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10712   `MatTransposeColoring` to sparse `B`.
10713 
10714   Collective
10715 
10716   Input Parameters:
10717 + coloring - coloring context created with `MatTransposeColoringCreate()`
10718 - B        - sparse matrix
10719 
10720   Output Parameter:
10721 . Btdense - dense matrix $B^T$
10722 
10723   Level: developer
10724 
10725   Note:
10726   These are used internally for some implementations of `MatRARt()`
10727 
10728 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10729 @*/
10730 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10731 {
10732   PetscFunctionBegin;
10733   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10734   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10735   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10736 
10737   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10738   PetscFunctionReturn(PETSC_SUCCESS);
10739 }
10740 
10741 /*@C
10742   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10743   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10744   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10745   $C_{sp}$ from $C_{den}$.
10746 
10747   Collective
10748 
10749   Input Parameters:
10750 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10751 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10752 
10753   Output Parameter:
10754 . Csp - sparse matrix
10755 
10756   Level: developer
10757 
10758   Note:
10759   These are used internally for some implementations of `MatRARt()`
10760 
10761 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10762 @*/
10763 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10764 {
10765   PetscFunctionBegin;
10766   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10767   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10768   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10769 
10770   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10771   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10772   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10773   PetscFunctionReturn(PETSC_SUCCESS);
10774 }
10775 
10776 /*@C
10777   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10778 
10779   Collective
10780 
10781   Input Parameters:
10782 + mat        - the matrix product C
10783 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10784 
10785   Output Parameter:
10786 . color - the new coloring context
10787 
10788   Level: intermediate
10789 
10790 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10791           `MatTransColoringApplyDenToSp()`
10792 @*/
10793 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10794 {
10795   MatTransposeColoring c;
10796   MPI_Comm             comm;
10797 
10798   PetscFunctionBegin;
10799   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10800   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10801   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10802 
10803   c->ctype = iscoloring->ctype;
10804   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10805 
10806   *color = c;
10807   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10808   PetscFunctionReturn(PETSC_SUCCESS);
10809 }
10810 
10811 /*@
10812   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10813   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10814   same, otherwise it will be larger
10815 
10816   Not Collective
10817 
10818   Input Parameter:
10819 . mat - the matrix
10820 
10821   Output Parameter:
10822 . state - the current state
10823 
10824   Level: intermediate
10825 
10826   Notes:
10827   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10828   different matrices
10829 
10830   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10831 
10832   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10833 
10834 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10835 @*/
10836 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10837 {
10838   PetscFunctionBegin;
10839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10840   *state = mat->nonzerostate;
10841   PetscFunctionReturn(PETSC_SUCCESS);
10842 }
10843 
10844 /*@
10845   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10846   matrices from each processor
10847 
10848   Collective
10849 
10850   Input Parameters:
10851 + comm   - the communicators the parallel matrix will live on
10852 . seqmat - the input sequential matrices
10853 . n      - number of local columns (or `PETSC_DECIDE`)
10854 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10855 
10856   Output Parameter:
10857 . mpimat - the parallel matrix generated
10858 
10859   Level: developer
10860 
10861   Note:
10862   The number of columns of the matrix in EACH processor MUST be the same.
10863 
10864 .seealso: [](ch_matrices), `Mat`
10865 @*/
10866 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10867 {
10868   PetscMPIInt size;
10869 
10870   PetscFunctionBegin;
10871   PetscCallMPI(MPI_Comm_size(comm, &size));
10872   if (size == 1) {
10873     if (reuse == MAT_INITIAL_MATRIX) {
10874       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10875     } else {
10876       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10877     }
10878     PetscFunctionReturn(PETSC_SUCCESS);
10879   }
10880 
10881   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");
10882 
10883   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10884   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10885   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10886   PetscFunctionReturn(PETSC_SUCCESS);
10887 }
10888 
10889 /*@
10890   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10891 
10892   Collective
10893 
10894   Input Parameters:
10895 + A - the matrix to create subdomains from
10896 - N - requested number of subdomains
10897 
10898   Output Parameters:
10899 + n   - number of subdomains resulting on this MPI process
10900 - iss - `IS` list with indices of subdomains on this MPI process
10901 
10902   Level: advanced
10903 
10904   Note:
10905   The number of subdomains must be smaller than the communicator size
10906 
10907 .seealso: [](ch_matrices), `Mat`, `IS`
10908 @*/
10909 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10910 {
10911   MPI_Comm    comm, subcomm;
10912   PetscMPIInt size, rank, color;
10913   PetscInt    rstart, rend, k;
10914 
10915   PetscFunctionBegin;
10916   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10917   PetscCallMPI(MPI_Comm_size(comm, &size));
10918   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10919   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);
10920   *n    = 1;
10921   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10922   color = rank / k;
10923   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10924   PetscCall(PetscMalloc1(1, iss));
10925   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10926   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10927   PetscCallMPI(MPI_Comm_free(&subcomm));
10928   PetscFunctionReturn(PETSC_SUCCESS);
10929 }
10930 
10931 /*@
10932   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10933 
10934   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10935   If they are not the same, uses `MatMatMatMult()`.
10936 
10937   Once the coarse grid problem is constructed, correct for interpolation operators
10938   that are not of full rank, which can legitimately happen in the case of non-nested
10939   geometric multigrid.
10940 
10941   Input Parameters:
10942 + restrct     - restriction operator
10943 . dA          - fine grid matrix
10944 . interpolate - interpolation operator
10945 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10946 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10947 
10948   Output Parameter:
10949 . A - the Galerkin coarse matrix
10950 
10951   Options Database Key:
10952 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10953 
10954   Level: developer
10955 
10956 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10957 @*/
10958 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10959 {
10960   IS  zerorows;
10961   Vec diag;
10962 
10963   PetscFunctionBegin;
10964   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10965   /* Construct the coarse grid matrix */
10966   if (interpolate == restrct) {
10967     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10968   } else {
10969     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10970   }
10971 
10972   /* If the interpolation matrix is not of full rank, A will have zero rows.
10973      This can legitimately happen in the case of non-nested geometric multigrid.
10974      In that event, we set the rows of the matrix to the rows of the identity,
10975      ignoring the equations (as the RHS will also be zero). */
10976 
10977   PetscCall(MatFindZeroRows(*A, &zerorows));
10978 
10979   if (zerorows != NULL) { /* if there are any zero rows */
10980     PetscCall(MatCreateVecs(*A, &diag, NULL));
10981     PetscCall(MatGetDiagonal(*A, diag));
10982     PetscCall(VecISSet(diag, zerorows, 1.0));
10983     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10984     PetscCall(VecDestroy(&diag));
10985     PetscCall(ISDestroy(&zerorows));
10986   }
10987   PetscFunctionReturn(PETSC_SUCCESS);
10988 }
10989 
10990 /*@C
10991   MatSetOperation - Allows user to set a matrix operation for any matrix type
10992 
10993   Logically Collective
10994 
10995   Input Parameters:
10996 + mat - the matrix
10997 . op  - the name of the operation
10998 - f   - the function that provides the operation
10999 
11000   Level: developer
11001 
11002   Example Usage:
11003 .vb
11004   extern PetscErrorCode usermult(Mat, Vec, Vec);
11005 
11006   PetscCall(MatCreateXXX(comm, ..., &A));
11007   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11008 .ve
11009 
11010   Notes:
11011   See the file `include/petscmat.h` for a complete list of matrix
11012   operations, which all have the form MATOP_<OPERATION>, where
11013   <OPERATION> is the name (in all capital letters) of the
11014   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11015 
11016   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11017   sequence as the usual matrix interface routines, since they
11018   are intended to be accessed via the usual matrix interface
11019   routines, e.g.,
11020 .vb
11021   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11022 .ve
11023 
11024   In particular each function MUST return `PETSC_SUCCESS` on success and
11025   nonzero on failure.
11026 
11027   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11028 
11029 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11030 @*/
11031 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11032 {
11033   PetscFunctionBegin;
11034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11035   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11036   (((void (**)(void))mat->ops)[op]) = f;
11037   PetscFunctionReturn(PETSC_SUCCESS);
11038 }
11039 
11040 /*@C
11041   MatGetOperation - Gets a matrix operation for any matrix type.
11042 
11043   Not Collective
11044 
11045   Input Parameters:
11046 + mat - the matrix
11047 - op  - the name of the operation
11048 
11049   Output Parameter:
11050 . f - the function that provides the operation
11051 
11052   Level: developer
11053 
11054   Example Usage:
11055 .vb
11056   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11057 
11058   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11059 .ve
11060 
11061   Notes:
11062   See the file include/petscmat.h for a complete list of matrix
11063   operations, which all have the form MATOP_<OPERATION>, where
11064   <OPERATION> is the name (in all capital letters) of the
11065   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11066 
11067   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11068 
11069 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11070 @*/
11071 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11072 {
11073   PetscFunctionBegin;
11074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11075   *f = (((void (**)(void))mat->ops)[op]);
11076   PetscFunctionReturn(PETSC_SUCCESS);
11077 }
11078 
11079 /*@
11080   MatHasOperation - Determines whether the given matrix supports the particular operation.
11081 
11082   Not Collective
11083 
11084   Input Parameters:
11085 + mat - the matrix
11086 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11087 
11088   Output Parameter:
11089 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11090 
11091   Level: advanced
11092 
11093   Note:
11094   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11095 
11096 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11097 @*/
11098 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11099 {
11100   PetscFunctionBegin;
11101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11102   PetscAssertPointer(has, 3);
11103   if (mat->ops->hasoperation) {
11104     PetscUseTypeMethod(mat, hasoperation, op, has);
11105   } else {
11106     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11107     else {
11108       *has = PETSC_FALSE;
11109       if (op == MATOP_CREATE_SUBMATRIX) {
11110         PetscMPIInt size;
11111 
11112         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11113         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11114       }
11115     }
11116   }
11117   PetscFunctionReturn(PETSC_SUCCESS);
11118 }
11119 
11120 /*@
11121   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11122 
11123   Collective
11124 
11125   Input Parameter:
11126 . mat - the matrix
11127 
11128   Output Parameter:
11129 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11130 
11131   Level: beginner
11132 
11133 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11134 @*/
11135 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11136 {
11137   PetscFunctionBegin;
11138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11139   PetscValidType(mat, 1);
11140   PetscAssertPointer(cong, 2);
11141   if (!mat->rmap || !mat->cmap) {
11142     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11143     PetscFunctionReturn(PETSC_SUCCESS);
11144   }
11145   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11146     PetscCall(PetscLayoutSetUp(mat->rmap));
11147     PetscCall(PetscLayoutSetUp(mat->cmap));
11148     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11149     if (*cong) mat->congruentlayouts = 1;
11150     else mat->congruentlayouts = 0;
11151   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11152   PetscFunctionReturn(PETSC_SUCCESS);
11153 }
11154 
11155 PetscErrorCode MatSetInf(Mat A)
11156 {
11157   PetscFunctionBegin;
11158   PetscUseTypeMethod(A, setinf);
11159   PetscFunctionReturn(PETSC_SUCCESS);
11160 }
11161 
11162 /*@C
11163   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
11164   and possibly removes small values from the graph structure.
11165 
11166   Collective
11167 
11168   Input Parameters:
11169 + A       - the matrix
11170 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11171 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11172 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11173 . num_idx - size of 'index' array
11174 - index   - array of block indices to use for graph strength of connection weight
11175 
11176   Output Parameter:
11177 . graph - the resulting graph
11178 
11179   Level: advanced
11180 
11181 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11182 @*/
11183 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11184 {
11185   PetscFunctionBegin;
11186   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11187   PetscValidType(A, 1);
11188   PetscValidLogicalCollectiveBool(A, scale, 3);
11189   PetscAssertPointer(graph, 7);
11190   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11191   PetscFunctionReturn(PETSC_SUCCESS);
11192 }
11193 
11194 /*@
11195   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11196   meaning the same memory is used for the matrix, and no new memory is allocated.
11197 
11198   Collective
11199 
11200   Input Parameters:
11201 + A    - the matrix
11202 - 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
11203 
11204   Level: intermediate
11205 
11206   Developer Note:
11207   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11208   of the arrays in the data structure are unneeded.
11209 
11210 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11211 @*/
11212 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11213 {
11214   PetscFunctionBegin;
11215   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11216   PetscUseTypeMethod(A, eliminatezeros, keep);
11217   PetscFunctionReturn(PETSC_SUCCESS);
11218 }
11219